@sellable/mcp 0.1.949 → 0.1.951-wip.sendercontext.20261001.1
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/agent-tool-names.d.ts +2 -2
- package/dist/agent-tool-names.js +4 -0
- package/dist/server.js +10 -4
- package/dist/tools/registry.d.ts +87 -0
- package/dist/tools/senders.d.ts +107 -0
- package/dist/tools/senders.js +168 -0
- package/package.json +1 -1
- package/skills/first-campaign-onboarding/SKILL.md +28 -10
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
* manifests. Keep this free of tool implementation imports so Next can bundle
|
|
4
4
|
* it; registry parity is enforced in sellable-agent-tool-policy.test.ts.
|
|
5
5
|
*/
|
|
6
|
-
export declare const SELLABLE_MCP_TOOL_NAMES: readonly ["add_column", "add_on_demand_leads", "add_rubric_item", "add_teammate", "add_to_comment_campaign", "add_to_connection_campaign", "add_to_inmail_campaign", "add_to_post_campaign", "archive_campaign", "attach_recommended_sequence", "attach_sequence", "bootstrap_create_campaign", "bootstrap_engage", "bootstrap_engage_multi", "bootstrap_find_leads", "bulk_enrich_with_prospeo", "calculate_linkedin_hook_preview", "cancel_campaign_message_preparation", "cancel_find_leads", "cancel_lead_import", "capture_post_idea", "check_inbox_reply_eligibility", "check_rubric", "commit_blueprint", "complete_sender_research", "confirm_harvest_job_companies", "confirm_lead_list", "confirm_prospeo_company_accounts", "copy_sender_config", "create_campaign", "create_on_demand_campaign", "create_on_demand_table", "create_table", "create_workflow_table", "create_workspace", "customer_program", "decide_agent_endpoint_proposal", "delete_column", "delete_rubric_item", "draft_rubrics", "duplicate_campaign", "enrich_with_prospeo", "export_table_csv", "export_workspace_csv", "fetch_company", "fetch_company_posts", "fetch_linkedin_posts", "fetch_linkedin_profile", "fetch_post_engagers", "fill_campaign_horizon", "get_active_workspace", "get_agent_endpoint_run", "get_agent_generation_routing", "get_agent_soul", "get_auth_status", "get_campaign", "get_campaign_context", "get_campaign_framework", "get_campaign_message_preparation_status", "get_campaign_messages_preview", "get_campaign_navigation_state", "get_campaign_refill_state", "get_campaign_table_schema", "get_campaign_waterfall", "get_campaigns", "get_column_schema", "get_company_info", "get_engage_memory", "get_engage_state", "get_engaged_posts", "get_find_leads_run", "get_inbox_thread", "get_integration_connection_status", "get_linkedin_profile", "get_or_create_direct_campaign_table", "get_post_draft", "get_post_find_leads_scout_registry", "get_post_idea", "get_prospeo_credits", "get_provider_prompt", "get_published_post", "get_refill_target_plan", "get_rows", "get_rows_minimal", "get_runtime_identity", "get_scheduler_fill_capacity", "get_sender", "get_sender_routing", "get_source_scout_registry", "get_subskill_asset", "get_subskill_prompt", "get_table_rows", "get_user_posts", "get_workspace", "import_leads", "init_on_demand_sequence", "integrations_call_tool", "integrations_describe_tool", "integrations_list_tools", "list_agent_endpoint_runs", "list_agent_endpoints", "list_column_types", "list_dnc_entries", "list_post_draft_iterations", "list_post_drafts", "list_post_ideas", "list_published_posts", "list_senders", "list_subskill_prompts", "list_tables", "list_workspaces", "load_csv_dnc_entries", "load_csv_domains", "load_csv_linkedin_leads", "lookup_sales_nav_filter", "mark_post_published", "migrate_flat_configs", "opportunity_sequence_enroll", "opportunity_sequence_next_page", "opportunity_sequence_record", "pause_campaign", "pause_direct_campaign", "pause_on_demand_campaign", "preflight_find_leads_provider", "prepare_campaign_ab_test", "publish_agent_endpoint", "queue_campaign_cells", "queue_cells", "record_campaign_review_batch", "record_engage_proven_search", "refill_sends", "refill_v3_advance", "refill_v3_continue", "refill_v3_edit_selected_campaign", "refill_v3_fill_ready", "refill_v3_world_state", "refresh_paid_inmail_credits", "refresh_sender_engagement", "reissue_find_leads_watch_link", "render_linkedin_post_preview", "reorder_columns", "resolve_campaign_fill_route", "revise_message_template_and_rerun", "rotate_agent_endpoint_key", "run_scheduler_sweep", "save_domain_filters", "save_hook_research", "save_post_draft", "save_rubrics", "search_apollo", "search_available_integrations", "search_engagement_posts", "search_harvest_jobs", "search_inbox_threads", "search_prospeo", "search_prospeo_companies", "search_sales_nav", "search_signals", "search_subskill_prompts", "select_campaign_cells", "select_necessary_rubrics", "select_promising_posts", "send_inbox_draft", "send_inbox_manual_reply", "set_active_workspace", "set_agent_generation_flags", "set_campaign_waterfall_order", "set_company_info", "set_engage_state", "set_engage_style_guide", "set_headline_icp_criteria", "set_sender_calendar_link", "set_sender_routing", "setup_evergreen_campaigns", "start_campaign", "start_campaign_message_preparation", "start_cli_login", "start_direct_campaign", "start_integration_connection", "start_on_demand_campaign", "stop_agent_endpoint_run", "update_agent_soul", "update_campaign", "update_campaign_brief", "update_cell", "update_column", "update_find_leads_run", "update_inbox_draft", "update_post_draft", "update_published_post_metrics", "update_rubric_item", "upsert_engage_tracked_person", "upsert_rubric", "validate_campaign1_kickoff_handoff", "verify_table_row", "wait_for_campaign_processing", "wait_for_campaign_table_ready", "wait_for_cli_login", "wait_for_find_leads_run", "wait_for_lead_list_ready", "wait_for_rubric_results"];
|
|
6
|
+
export declare const SELLABLE_MCP_TOOL_NAMES: readonly ["add_column", "add_on_demand_leads", "add_rubric_item", "add_teammate", "add_to_comment_campaign", "add_to_connection_campaign", "add_to_inmail_campaign", "add_to_post_campaign", "archive_campaign", "attach_recommended_sequence", "attach_sequence", "bootstrap_create_campaign", "bootstrap_engage", "bootstrap_engage_multi", "bootstrap_find_leads", "bulk_enrich_with_prospeo", "calculate_linkedin_hook_preview", "cancel_campaign_message_preparation", "cancel_find_leads", "cancel_lead_import", "capture_post_idea", "check_inbox_reply_eligibility", "check_rubric", "commit_blueprint", "complete_sender_research", "confirm_harvest_job_companies", "confirm_lead_list", "confirm_prospeo_company_accounts", "copy_sender_config", "create_campaign", "create_on_demand_campaign", "create_on_demand_table", "create_table", "create_workflow_table", "create_workspace", "customer_program", "decide_agent_endpoint_proposal", "delete_column", "delete_rubric_item", "draft_rubrics", "duplicate_campaign", "enrich_with_prospeo", "export_table_csv", "export_workspace_csv", "fetch_company", "fetch_company_posts", "fetch_linkedin_posts", "fetch_linkedin_profile", "fetch_post_engagers", "fill_campaign_horizon", "get_active_workspace", "get_agent_endpoint_run", "get_agent_generation_routing", "get_agent_soul", "get_auth_status", "get_campaign", "get_campaign_context", "get_campaign_framework", "get_campaign_message_preparation_status", "get_campaign_messages_preview", "get_campaign_navigation_state", "get_campaign_refill_state", "get_campaign_table_schema", "get_campaign_waterfall", "get_campaigns", "get_column_schema", "get_company_info", "get_engage_memory", "get_engage_state", "get_engaged_posts", "get_find_leads_run", "get_inbox_thread", "get_integration_connection_status", "get_linkedin_profile", "get_or_create_direct_campaign_table", "get_post_draft", "get_post_find_leads_scout_registry", "get_post_idea", "get_prospeo_credits", "get_provider_prompt", "get_published_post", "get_refill_target_plan", "get_rows", "get_rows_minimal", "get_runtime_identity", "get_scheduler_fill_capacity", "get_sender", "get_sender_routing", "get_source_scout_registry", "get_subskill_asset", "get_subskill_prompt", "get_table_rows", "get_user_posts", "get_workspace", "import_leads", "init_on_demand_sequence", "integrations_call_tool", "integrations_describe_tool", "integrations_list_tools", "list_agent_endpoint_runs", "list_agent_endpoints", "list_column_types", "list_dnc_entries", "list_post_draft_iterations", "list_post_drafts", "list_post_ideas", "list_published_posts", "list_senders", "list_subskill_prompts", "list_tables", "list_workspaces", "load_csv_dnc_entries", "load_csv_domains", "load_csv_linkedin_leads", "lookup_sales_nav_filter", "mark_post_published", "migrate_flat_configs", "opportunity_sequence_enroll", "opportunity_sequence_next_page", "opportunity_sequence_record", "pause_campaign", "pause_direct_campaign", "pause_on_demand_campaign", "preflight_find_leads_provider", "prepare_campaign_ab_test", "publish_agent_endpoint", "queue_campaign_cells", "queue_cells", "record_campaign_review_batch", "record_engage_proven_search", "refill_sends", "refill_v3_advance", "refill_v3_continue", "refill_v3_edit_selected_campaign", "refill_v3_fill_ready", "refill_v3_world_state", "refresh_paid_inmail_credits", "refresh_sender_engagement", "reissue_find_leads_watch_link", "render_linkedin_post_preview", "reorder_columns", "resolve_campaign_fill_route", "revise_message_template_and_rerun", "rotate_agent_endpoint_key", "run_scheduler_sweep", "save_domain_filters", "save_hook_research", "save_post_draft", "save_rubrics", "search_apollo", "search_available_integrations", "search_engagement_posts", "search_harvest_jobs", "search_inbox_threads", "search_prospeo", "search_prospeo_companies", "search_sales_nav", "search_signals", "search_subskill_prompts", "select_campaign_cells", "select_necessary_rubrics", "select_promising_posts", "send_inbox_draft", "send_inbox_manual_reply", "set_active_workspace", "set_agent_generation_flags", "set_campaign_waterfall_order", "set_company_info", "set_engage_state", "set_engage_style_guide", "set_headline_icp_criteria", "set_sender_calendar_link", "set_sender_context", "set_sender_routing", "setup_evergreen_campaigns", "start_campaign", "start_campaign_message_preparation", "start_cli_login", "start_direct_campaign", "start_integration_connection", "start_on_demand_campaign", "stop_agent_endpoint_run", "update_agent_soul", "update_campaign", "update_campaign_brief", "update_cell", "update_column", "update_find_leads_run", "update_inbox_draft", "update_post_draft", "update_published_post_metrics", "update_rubric_item", "upsert_engage_tracked_person", "upsert_rubric", "validate_campaign1_kickoff_handoff", "verify_table_row", "wait_for_campaign_processing", "wait_for_campaign_table_ready", "wait_for_cli_login", "wait_for_find_leads_run", "wait_for_lead_list_ready", "wait_for_rubric_results"];
|
|
7
7
|
/**
|
|
8
8
|
* Explicit mutation classification lives beside (but outside) the flat tool
|
|
9
9
|
* registry. Neither this list nor `isMutatingTool` is an input to
|
|
10
10
|
* `compileAgentToolPolicy`, so editing it cannot move the fleet-pinned
|
|
11
11
|
* `policyHash`.
|
|
12
12
|
*/
|
|
13
|
-
export declare const MUTATING_TOOL_NAMES: readonly ["create_table", "publish_agent_endpoint", "rotate_agent_endpoint_key", "decide_agent_endpoint_proposal", "stop_agent_endpoint_run", "pause_campaign", "archive_campaign", "update_campaign", "fill_campaign_horizon", "set_campaign_waterfall_order", "set_sender_routing", "set_agent_generation_flags", "send_inbox_draft", "send_inbox_manual_reply", "load_csv_dnc_entries", "update_cell", "queue_cells", "check_rubric", "queue_campaign_cells", "start_campaign_message_preparation", "opportunity_sequence_enroll", "opportunity_sequence_record", "refill_v3_fill_ready", "refill_v3_edit_selected_campaign", "refill_v3_advance", "refill_v3_continue"];
|
|
13
|
+
export declare const MUTATING_TOOL_NAMES: readonly ["create_table", "publish_agent_endpoint", "rotate_agent_endpoint_key", "decide_agent_endpoint_proposal", "stop_agent_endpoint_run", "pause_campaign", "archive_campaign", "update_campaign", "fill_campaign_horizon", "set_campaign_waterfall_order", "set_sender_routing", "set_sender_context", "set_agent_generation_flags", "send_inbox_draft", "send_inbox_manual_reply", "load_csv_dnc_entries", "update_cell", "queue_cells", "check_rubric", "queue_campaign_cells", "start_campaign_message_preparation", "opportunity_sequence_enroll", "opportunity_sequence_record", "refill_v3_fill_ready", "refill_v3_edit_selected_campaign", "refill_v3_advance", "refill_v3_continue"];
|
|
14
14
|
export declare function isMutatingTool(name: string): boolean;
|
|
15
15
|
export declare const CROSS_WORKSPACE_EXPLICIT_WORKSPACE_REQUIRED: {
|
|
16
16
|
readonly code: "cross_workspace_explicit_workspace_required";
|
package/dist/agent-tool-names.js
CHANGED
|
@@ -176,6 +176,7 @@ export const SELLABLE_MCP_TOOL_NAMES = [
|
|
|
176
176
|
"set_engage_style_guide",
|
|
177
177
|
"set_headline_icp_criteria",
|
|
178
178
|
"set_sender_calendar_link",
|
|
179
|
+
"set_sender_context",
|
|
179
180
|
"set_sender_routing",
|
|
180
181
|
"setup_evergreen_campaigns",
|
|
181
182
|
"start_campaign",
|
|
@@ -227,6 +228,9 @@ export const MUTATING_TOOL_NAMES = [
|
|
|
227
228
|
"fill_campaign_horizon",
|
|
228
229
|
"set_campaign_waterfall_order",
|
|
229
230
|
"set_sender_routing",
|
|
231
|
+
// A sender's personal context is what the message writer says about a real
|
|
232
|
+
// person, so a cross-workspace caller must name the workspace it means.
|
|
233
|
+
"set_sender_context",
|
|
230
234
|
"set_agent_generation_flags",
|
|
231
235
|
"send_inbox_draft",
|
|
232
236
|
"send_inbox_manual_reply",
|
package/dist/server.js
CHANGED
|
@@ -34,9 +34,9 @@ import { handleReorderColumns } from "./tools/column-reorder.js";
|
|
|
34
34
|
import { handleGetColumnSchema, handleListColumnTypes, } from "./tools/column-schema.js";
|
|
35
35
|
import { handleUpdateColumn } from "./tools/column-update.js";
|
|
36
36
|
import { getCompanyInfoTool, setCompanyInfoTool, } from "./tools/company-info.js";
|
|
37
|
-
import { customerProgramTool } from "./tools/customer-program.js";
|
|
38
37
|
import { calculateLinkedInHookPreviewTool, capturePostIdeaTool, getPostDraftTool, getPostIdeaTool, getPublishedPostTool, listPostDraftIterationsTool, listPostDraftsTool, listPostIdeasTool, listPublishedPostsTool, markPostPublishedTool, renderLinkedInPostPreviewTool, saveHookResearchTool, savePostDraftTool, updatePostDraftTool, updatePublishedPostMetricsTool, } from "./tools/content-posts.js";
|
|
39
38
|
import { getCampaignContext, hydrateCampaignContextFromCampaign, markCampaignContextDirty, } from "./tools/context.js";
|
|
39
|
+
import { customerProgramTool } from "./tools/customer-program.js";
|
|
40
40
|
import { addToCommentCampaign, addToConnectionCampaign, addToInmailCampaign, addToPostCampaign, getEngagedPosts, getOrCreateDirectCampaignTable, pauseDirectCampaign, startDirectCampaign, } from "./tools/direct-campaigns.js";
|
|
41
41
|
import { bootstrapEngage, bootstrapEngageMulti, } from "./tools/engage-bootstrap.js";
|
|
42
42
|
import { searchEngagementPosts } from "./tools/engage-discovery.js";
|
|
@@ -75,7 +75,7 @@ import { getRuntimeIdentityTool } from "./tools/runtime-identity.js";
|
|
|
75
75
|
import { getSchedulerFillCapacity } from "./tools/scheduler-fill-capacity.js";
|
|
76
76
|
import { runSchedulerSweep } from "./tools/scheduler-run.js";
|
|
77
77
|
import { getSenderRoutingTool, setSenderRoutingTool, } from "./tools/sender-routing.js";
|
|
78
|
-
import { getSender, listSenders, refreshPaidInmailCredits, setSenderCalendarLink, } from "./tools/senders.js";
|
|
78
|
+
import { getSender, listSenders, refreshPaidInmailCredits, setSenderCalendarLink, setSenderContext, } from "./tools/senders.js";
|
|
79
79
|
import { attachRecommendedSequence, attachSequence, createWorkflowTable, } from "./tools/sequencer.js";
|
|
80
80
|
import { setupEvergreenCampaigns } from "./tools/setup-evergreen-campaigns.js";
|
|
81
81
|
import { createTable, exportTableCsv, listTables } from "./tools/tables.js";
|
|
@@ -201,8 +201,11 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
201
201
|
ok: false,
|
|
202
202
|
error: boundary.authorization.code,
|
|
203
203
|
decision: "DENY",
|
|
204
|
-
...(boundary.authorization.code ===
|
|
205
|
-
|
|
204
|
+
...(boundary.authorization.code ===
|
|
205
|
+
"managed_agent_auth_unavailable"
|
|
206
|
+
? {
|
|
207
|
+
message: "Managed authentication is unavailable. The runtime supervisor must restore it; do not copy personal credentials, start browser login, or retry a Calendar mutation automatically.",
|
|
208
|
+
}
|
|
206
209
|
: {}),
|
|
207
210
|
}),
|
|
208
211
|
},
|
|
@@ -862,6 +865,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
862
865
|
case "set_sender_calendar_link":
|
|
863
866
|
result = await setSenderCalendarLink(args);
|
|
864
867
|
break;
|
|
868
|
+
case "set_sender_context":
|
|
869
|
+
result = await setSenderContext(args);
|
|
870
|
+
break;
|
|
865
871
|
case "refresh_paid_inmail_credits":
|
|
866
872
|
result = await refreshPaidInmailCredits(args);
|
|
867
873
|
break;
|
package/dist/tools/registry.d.ts
CHANGED
|
@@ -7486,6 +7486,8 @@ export declare const allTools: ({
|
|
|
7486
7486
|
expectedCalendarLink?: undefined;
|
|
7487
7487
|
expectedCalendarLinkRevision?: undefined;
|
|
7488
7488
|
force?: undefined;
|
|
7489
|
+
senderContext?: undefined;
|
|
7490
|
+
expectedUpdatedAt?: undefined;
|
|
7489
7491
|
};
|
|
7490
7492
|
required: string[];
|
|
7491
7493
|
additionalProperties: boolean;
|
|
@@ -7527,6 +7529,8 @@ export declare const allTools: ({
|
|
|
7527
7529
|
threshold?: undefined;
|
|
7528
7530
|
maxStalenessSeconds?: undefined;
|
|
7529
7531
|
paidInmailCreditsMaxStalenessSeconds?: undefined;
|
|
7532
|
+
senderContext?: undefined;
|
|
7533
|
+
expectedUpdatedAt?: undefined;
|
|
7530
7534
|
};
|
|
7531
7535
|
required: string[];
|
|
7532
7536
|
additionalProperties: boolean;
|
|
@@ -7610,6 +7614,89 @@ export declare const allTools: ({
|
|
|
7610
7614
|
idempotentHint: boolean;
|
|
7611
7615
|
openWorldHint: boolean;
|
|
7612
7616
|
};
|
|
7617
|
+
} | {
|
|
7618
|
+
name: string;
|
|
7619
|
+
description: string;
|
|
7620
|
+
inputSchema: {
|
|
7621
|
+
type: string;
|
|
7622
|
+
properties: {
|
|
7623
|
+
senderId: {
|
|
7624
|
+
type: string;
|
|
7625
|
+
minLength: number;
|
|
7626
|
+
description?: undefined;
|
|
7627
|
+
};
|
|
7628
|
+
workspaceId: {
|
|
7629
|
+
type: string;
|
|
7630
|
+
minLength: number;
|
|
7631
|
+
description?: undefined;
|
|
7632
|
+
};
|
|
7633
|
+
senderContext: {
|
|
7634
|
+
type: string[];
|
|
7635
|
+
properties: {
|
|
7636
|
+
workStories: {
|
|
7637
|
+
readonly type: "array";
|
|
7638
|
+
readonly maxItems: 10;
|
|
7639
|
+
readonly items: {
|
|
7640
|
+
readonly type: "string";
|
|
7641
|
+
readonly minLength: 1;
|
|
7642
|
+
readonly maxLength: 3000;
|
|
7643
|
+
};
|
|
7644
|
+
};
|
|
7645
|
+
personalNotes: {
|
|
7646
|
+
readonly type: "array";
|
|
7647
|
+
readonly maxItems: 10;
|
|
7648
|
+
readonly items: {
|
|
7649
|
+
readonly type: "string";
|
|
7650
|
+
readonly minLength: 1;
|
|
7651
|
+
readonly maxLength: 3000;
|
|
7652
|
+
};
|
|
7653
|
+
};
|
|
7654
|
+
voiceExamples: {
|
|
7655
|
+
readonly type: "array";
|
|
7656
|
+
readonly maxItems: 10;
|
|
7657
|
+
readonly items: {
|
|
7658
|
+
readonly type: "string";
|
|
7659
|
+
readonly minLength: 1;
|
|
7660
|
+
readonly maxLength: 3000;
|
|
7661
|
+
};
|
|
7662
|
+
};
|
|
7663
|
+
sourcesAndLimits: {
|
|
7664
|
+
readonly type: "array";
|
|
7665
|
+
readonly maxItems: 10;
|
|
7666
|
+
readonly items: {
|
|
7667
|
+
readonly type: "string";
|
|
7668
|
+
readonly minLength: 1;
|
|
7669
|
+
readonly maxLength: 3000;
|
|
7670
|
+
};
|
|
7671
|
+
};
|
|
7672
|
+
};
|
|
7673
|
+
additionalProperties: boolean;
|
|
7674
|
+
};
|
|
7675
|
+
expectedUpdatedAt: {
|
|
7676
|
+
readonly type: readonly ["string", "null"];
|
|
7677
|
+
};
|
|
7678
|
+
actionType?: undefined;
|
|
7679
|
+
campaignId?: undefined;
|
|
7680
|
+
tableId?: undefined;
|
|
7681
|
+
columnId?: undefined;
|
|
7682
|
+
threshold?: undefined;
|
|
7683
|
+
maxStalenessSeconds?: undefined;
|
|
7684
|
+
paidInmailCreditsMaxStalenessSeconds?: undefined;
|
|
7685
|
+
calendarLink?: undefined;
|
|
7686
|
+
expectedCalendarLink?: undefined;
|
|
7687
|
+
expectedCalendarLinkRevision?: undefined;
|
|
7688
|
+
force?: undefined;
|
|
7689
|
+
};
|
|
7690
|
+
required: string[];
|
|
7691
|
+
additionalProperties: boolean;
|
|
7692
|
+
};
|
|
7693
|
+
annotations: {
|
|
7694
|
+
readOnlyHint: boolean;
|
|
7695
|
+
destructiveHint: boolean;
|
|
7696
|
+
idempotentHint: boolean;
|
|
7697
|
+
openWorldHint: boolean;
|
|
7698
|
+
};
|
|
7699
|
+
outputSchema?: undefined;
|
|
7613
7700
|
} | {
|
|
7614
7701
|
name: string;
|
|
7615
7702
|
description: string;
|
package/dist/tools/senders.d.ts
CHANGED
|
@@ -180,6 +180,8 @@ export declare const senderToolDefinitions: ({
|
|
|
180
180
|
expectedCalendarLink?: undefined;
|
|
181
181
|
expectedCalendarLinkRevision?: undefined;
|
|
182
182
|
force?: undefined;
|
|
183
|
+
senderContext?: undefined;
|
|
184
|
+
expectedUpdatedAt?: undefined;
|
|
183
185
|
};
|
|
184
186
|
required: never[];
|
|
185
187
|
additionalProperties: boolean;
|
|
@@ -213,6 +215,8 @@ export declare const senderToolDefinitions: ({
|
|
|
213
215
|
expectedCalendarLink?: undefined;
|
|
214
216
|
expectedCalendarLinkRevision?: undefined;
|
|
215
217
|
force?: undefined;
|
|
218
|
+
senderContext?: undefined;
|
|
219
|
+
expectedUpdatedAt?: undefined;
|
|
216
220
|
};
|
|
217
221
|
required: string[];
|
|
218
222
|
additionalProperties: boolean;
|
|
@@ -267,6 +271,8 @@ export declare const senderToolDefinitions: ({
|
|
|
267
271
|
expectedCalendarLink?: undefined;
|
|
268
272
|
expectedCalendarLinkRevision?: undefined;
|
|
269
273
|
force?: undefined;
|
|
274
|
+
senderContext?: undefined;
|
|
275
|
+
expectedUpdatedAt?: undefined;
|
|
270
276
|
};
|
|
271
277
|
required: string[];
|
|
272
278
|
additionalProperties: boolean;
|
|
@@ -308,6 +314,8 @@ export declare const senderToolDefinitions: ({
|
|
|
308
314
|
threshold?: undefined;
|
|
309
315
|
maxStalenessSeconds?: undefined;
|
|
310
316
|
paidInmailCreditsMaxStalenessSeconds?: undefined;
|
|
317
|
+
senderContext?: undefined;
|
|
318
|
+
expectedUpdatedAt?: undefined;
|
|
311
319
|
};
|
|
312
320
|
required: string[];
|
|
313
321
|
additionalProperties: boolean;
|
|
@@ -391,9 +399,108 @@ export declare const senderToolDefinitions: ({
|
|
|
391
399
|
idempotentHint: boolean;
|
|
392
400
|
openWorldHint: boolean;
|
|
393
401
|
};
|
|
402
|
+
} | {
|
|
403
|
+
name: string;
|
|
404
|
+
description: string;
|
|
405
|
+
inputSchema: {
|
|
406
|
+
type: string;
|
|
407
|
+
properties: {
|
|
408
|
+
senderId: {
|
|
409
|
+
type: string;
|
|
410
|
+
minLength: number;
|
|
411
|
+
description?: undefined;
|
|
412
|
+
};
|
|
413
|
+
workspaceId: {
|
|
414
|
+
type: string;
|
|
415
|
+
minLength: number;
|
|
416
|
+
description?: undefined;
|
|
417
|
+
};
|
|
418
|
+
senderContext: {
|
|
419
|
+
type: string[];
|
|
420
|
+
properties: {
|
|
421
|
+
workStories: {
|
|
422
|
+
readonly type: "array";
|
|
423
|
+
readonly maxItems: 10;
|
|
424
|
+
readonly items: {
|
|
425
|
+
readonly type: "string";
|
|
426
|
+
readonly minLength: 1;
|
|
427
|
+
readonly maxLength: 3000;
|
|
428
|
+
};
|
|
429
|
+
};
|
|
430
|
+
personalNotes: {
|
|
431
|
+
readonly type: "array";
|
|
432
|
+
readonly maxItems: 10;
|
|
433
|
+
readonly items: {
|
|
434
|
+
readonly type: "string";
|
|
435
|
+
readonly minLength: 1;
|
|
436
|
+
readonly maxLength: 3000;
|
|
437
|
+
};
|
|
438
|
+
};
|
|
439
|
+
voiceExamples: {
|
|
440
|
+
readonly type: "array";
|
|
441
|
+
readonly maxItems: 10;
|
|
442
|
+
readonly items: {
|
|
443
|
+
readonly type: "string";
|
|
444
|
+
readonly minLength: 1;
|
|
445
|
+
readonly maxLength: 3000;
|
|
446
|
+
};
|
|
447
|
+
};
|
|
448
|
+
sourcesAndLimits: {
|
|
449
|
+
readonly type: "array";
|
|
450
|
+
readonly maxItems: 10;
|
|
451
|
+
readonly items: {
|
|
452
|
+
readonly type: "string";
|
|
453
|
+
readonly minLength: 1;
|
|
454
|
+
readonly maxLength: 3000;
|
|
455
|
+
};
|
|
456
|
+
};
|
|
457
|
+
};
|
|
458
|
+
additionalProperties: boolean;
|
|
459
|
+
};
|
|
460
|
+
expectedUpdatedAt: {
|
|
461
|
+
readonly type: readonly ["string", "null"];
|
|
462
|
+
};
|
|
463
|
+
actionType?: undefined;
|
|
464
|
+
campaignId?: undefined;
|
|
465
|
+
tableId?: undefined;
|
|
466
|
+
columnId?: undefined;
|
|
467
|
+
threshold?: undefined;
|
|
468
|
+
maxStalenessSeconds?: undefined;
|
|
469
|
+
paidInmailCreditsMaxStalenessSeconds?: undefined;
|
|
470
|
+
calendarLink?: undefined;
|
|
471
|
+
expectedCalendarLink?: undefined;
|
|
472
|
+
expectedCalendarLinkRevision?: undefined;
|
|
473
|
+
force?: undefined;
|
|
474
|
+
};
|
|
475
|
+
required: string[];
|
|
476
|
+
additionalProperties: boolean;
|
|
477
|
+
};
|
|
478
|
+
annotations: {
|
|
479
|
+
readOnlyHint: boolean;
|
|
480
|
+
destructiveHint: boolean;
|
|
481
|
+
idempotentHint: boolean;
|
|
482
|
+
openWorldHint: boolean;
|
|
483
|
+
};
|
|
484
|
+
outputSchema?: undefined;
|
|
394
485
|
})[];
|
|
395
486
|
export declare function listSenders(input?: ListSendersInput): Promise<ListSendersResponse>;
|
|
396
487
|
export declare function setSenderCalendarLink(input: SetSenderCalendarLinkInput): Promise<SenderCalendarLinkToolResult>;
|
|
488
|
+
declare const SENDER_CONTEXT_LISTS: readonly ["workStories", "personalNotes", "voiceExamples", "sourcesAndLimits"];
|
|
489
|
+
export type SetSenderContextInput = {
|
|
490
|
+
senderId: string;
|
|
491
|
+
workspaceId: string;
|
|
492
|
+
senderContext: Partial<Record<(typeof SENDER_CONTEXT_LISTS)[number], string[]>> | null;
|
|
493
|
+
expectedUpdatedAt: string | null;
|
|
494
|
+
};
|
|
495
|
+
/** Save one sender's personal context through the compare-before-write route. */
|
|
496
|
+
export declare function setSenderContext(input: SetSenderContextInput): Promise<{
|
|
497
|
+
isError?: true | undefined;
|
|
498
|
+
structuredContent: Record<string, unknown>;
|
|
499
|
+
content: {
|
|
500
|
+
type: "text";
|
|
501
|
+
text: string;
|
|
502
|
+
}[];
|
|
503
|
+
}>;
|
|
397
504
|
export declare function getSender(input: GetSenderInput): Promise<SenderDetailResponse>;
|
|
398
505
|
export declare function refreshPaidInmailCredits(input: RefreshPaidInmailCreditsInput): Promise<RefreshPaidInmailCreditsResponse>;
|
|
399
506
|
export {};
|
package/dist/tools/senders.js
CHANGED
|
@@ -2,6 +2,11 @@ import { getApi, SellableApiError } from "../api.js";
|
|
|
2
2
|
import { isLinkedInProfileInput, normalizeLinkedInProfileInput, } from "./linkedin-url.js";
|
|
3
3
|
import { normalizeExplicitWorkspaceId, workspaceRequestOptions, } from "./workspace-context.js";
|
|
4
4
|
const nullableStringSchema = { type: ["string", "null"] };
|
|
5
|
+
const senderContextEntriesInputSchema = {
|
|
6
|
+
type: "array",
|
|
7
|
+
maxItems: 10,
|
|
8
|
+
items: { type: "string", minLength: 1, maxLength: 3000 },
|
|
9
|
+
};
|
|
5
10
|
const setSenderCalendarLinkOutputSchema = {
|
|
6
11
|
type: "object",
|
|
7
12
|
oneOf: [
|
|
@@ -346,6 +351,41 @@ export const senderToolDefinitions = [
|
|
|
346
351
|
openWorldHint: false,
|
|
347
352
|
},
|
|
348
353
|
},
|
|
354
|
+
{
|
|
355
|
+
name: "set_sender_context",
|
|
356
|
+
description: "Save one exact outbound sender's personal context: the four lists the message writer uses as that sender's fact bank and voice (workStories, personalNotes, voiceExamples, sourcesAndLimits). This is what a sender interview produces. It replaces the sender's whole saved context; it cannot touch another sender, the calendar link, writing style, dos/donts or Company Info. Read get_sender first and pass generationContext.updatedAt as expectedUpdatedAt (null when nothing is saved yet). Limits: at most 10 entries per list, 3000 characters per entry, 15000 UTF-8 bytes in all. Only write what the sender said or confirmed; never copy one sender's facts into another's. Pass senderContext: null to clear it.",
|
|
357
|
+
inputSchema: {
|
|
358
|
+
type: "object",
|
|
359
|
+
properties: {
|
|
360
|
+
senderId: { type: "string", minLength: 1 },
|
|
361
|
+
workspaceId: { type: "string", minLength: 1 },
|
|
362
|
+
senderContext: {
|
|
363
|
+
type: ["object", "null"],
|
|
364
|
+
properties: {
|
|
365
|
+
workStories: senderContextEntriesInputSchema,
|
|
366
|
+
personalNotes: senderContextEntriesInputSchema,
|
|
367
|
+
voiceExamples: senderContextEntriesInputSchema,
|
|
368
|
+
sourcesAndLimits: senderContextEntriesInputSchema,
|
|
369
|
+
},
|
|
370
|
+
additionalProperties: false,
|
|
371
|
+
},
|
|
372
|
+
expectedUpdatedAt: nullableStringSchema,
|
|
373
|
+
},
|
|
374
|
+
required: [
|
|
375
|
+
"senderId",
|
|
376
|
+
"workspaceId",
|
|
377
|
+
"senderContext",
|
|
378
|
+
"expectedUpdatedAt",
|
|
379
|
+
],
|
|
380
|
+
additionalProperties: false,
|
|
381
|
+
},
|
|
382
|
+
annotations: {
|
|
383
|
+
readOnlyHint: false,
|
|
384
|
+
destructiveHint: true,
|
|
385
|
+
idempotentHint: true,
|
|
386
|
+
openWorldHint: false,
|
|
387
|
+
},
|
|
388
|
+
},
|
|
349
389
|
];
|
|
350
390
|
export async function listSenders(input = {}) {
|
|
351
391
|
const api = getApi();
|
|
@@ -497,6 +537,134 @@ export async function setSenderCalendarLink(input) {
|
|
|
497
537
|
});
|
|
498
538
|
}
|
|
499
539
|
}
|
|
540
|
+
const SENDER_CONTEXT_LISTS = [
|
|
541
|
+
"workStories",
|
|
542
|
+
"personalNotes",
|
|
543
|
+
"voiceExamples",
|
|
544
|
+
"sourcesAndLimits",
|
|
545
|
+
];
|
|
546
|
+
function senderContextResult(value) {
|
|
547
|
+
return {
|
|
548
|
+
structuredContent: value,
|
|
549
|
+
content: [{ type: "text", text: JSON.stringify(value) }],
|
|
550
|
+
...(value.ok === true ? {} : { isError: true }),
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
function isSenderContextInput(value) {
|
|
554
|
+
if (value === null)
|
|
555
|
+
return true;
|
|
556
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
557
|
+
return false;
|
|
558
|
+
return Object.entries(value).every(([key, entries]) => SENDER_CONTEXT_LISTS.includes(key) &&
|
|
559
|
+
Array.isArray(entries) &&
|
|
560
|
+
entries.every((entry) => typeof entry === "string"));
|
|
561
|
+
}
|
|
562
|
+
/** Save one sender's personal context through the compare-before-write route. */
|
|
563
|
+
export async function setSenderContext(input) {
|
|
564
|
+
const candidate = input;
|
|
565
|
+
const record = candidate && typeof candidate === "object" && !Array.isArray(candidate)
|
|
566
|
+
? candidate
|
|
567
|
+
: null;
|
|
568
|
+
const senderId = record && typeof record.senderId === "string" ? record.senderId.trim() : "";
|
|
569
|
+
const workspaceId = record && typeof record.workspaceId === "string"
|
|
570
|
+
? record.workspaceId.trim()
|
|
571
|
+
: "";
|
|
572
|
+
const hasOwn = (key) => record !== null && Object.prototype.hasOwnProperty.call(record, key);
|
|
573
|
+
if (!record ||
|
|
574
|
+
!senderId ||
|
|
575
|
+
!workspaceId ||
|
|
576
|
+
!hasOwn("senderContext") ||
|
|
577
|
+
!isSenderContextInput(record.senderContext) ||
|
|
578
|
+
!hasOwn("expectedUpdatedAt") ||
|
|
579
|
+
!isNullableString(record.expectedUpdatedAt)) {
|
|
580
|
+
return senderContextResult({
|
|
581
|
+
ok: false,
|
|
582
|
+
code: "invalid_arguments",
|
|
583
|
+
message: "senderId, workspaceId, senderContext and expectedUpdatedAt are required with the documented types.",
|
|
584
|
+
status: null,
|
|
585
|
+
uncertain: false,
|
|
586
|
+
currentUpdatedAt: null,
|
|
587
|
+
guidance: "Read get_sender and retry with generationContext.updatedAt as expectedUpdatedAt (null when nothing is saved).",
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
const api = getApi();
|
|
591
|
+
try {
|
|
592
|
+
const receipt = await api.put(`/api/v3/mcp/senders/${encodeURIComponent(senderId)}/sender-context`, {
|
|
593
|
+
workspaceId,
|
|
594
|
+
senderContext: record.senderContext,
|
|
595
|
+
expectedUpdatedAt: record.expectedUpdatedAt,
|
|
596
|
+
}, workspaceRequestOptions(workspaceId));
|
|
597
|
+
if (!receipt ||
|
|
598
|
+
typeof receipt !== "object" ||
|
|
599
|
+
typeof receipt.updatedAt !== "string") {
|
|
600
|
+
return senderContextResult({
|
|
601
|
+
ok: false,
|
|
602
|
+
code: "malformed_sender_context_response",
|
|
603
|
+
message: "The sender-context save returned an incomplete receipt, so the final state is uncertain.",
|
|
604
|
+
status: null,
|
|
605
|
+
uncertain: true,
|
|
606
|
+
currentUpdatedAt: null,
|
|
607
|
+
guidance: "Reread get_sender and reconcile before retrying.",
|
|
608
|
+
});
|
|
609
|
+
}
|
|
610
|
+
return senderContextResult({
|
|
611
|
+
ok: true,
|
|
612
|
+
senderId,
|
|
613
|
+
workspaceId,
|
|
614
|
+
senderContext: receipt.senderContext ?? null,
|
|
615
|
+
previousUpdatedAt: record.expectedUpdatedAt,
|
|
616
|
+
updatedAt: receipt.updatedAt,
|
|
617
|
+
cleared: receipt.cleared === true,
|
|
618
|
+
});
|
|
619
|
+
}
|
|
620
|
+
catch (error) {
|
|
621
|
+
if (error instanceof SellableApiError) {
|
|
622
|
+
const body = parseErrorBody(error.body);
|
|
623
|
+
const code = safeErrorCode(body?.code, `http_${error.status}`);
|
|
624
|
+
const isConflict = error.status === 409 && code === "sender_context_conflict";
|
|
625
|
+
const uncertain = error.status >= 500;
|
|
626
|
+
return senderContextResult({
|
|
627
|
+
ok: false,
|
|
628
|
+
code,
|
|
629
|
+
message: isConflict
|
|
630
|
+
? "The sender's saved context changed after it was read."
|
|
631
|
+
: uncertain
|
|
632
|
+
? "The sender-context save did not complete with a confirmed result."
|
|
633
|
+
: error.isAuthError
|
|
634
|
+
? "Sellable authentication or authorization failed."
|
|
635
|
+
: error.status === 404
|
|
636
|
+
? "The sender was not found in the explicit workspace."
|
|
637
|
+
: "The sender context was not saved.",
|
|
638
|
+
status: error.status,
|
|
639
|
+
uncertain,
|
|
640
|
+
currentUpdatedAt: isConflict && isNullableString(body?.currentUpdatedAt)
|
|
641
|
+
? body.currentUpdatedAt
|
|
642
|
+
: null,
|
|
643
|
+
guidance: isConflict
|
|
644
|
+
? "Reread get_sender, merge with the newer context, and retry with its updatedAt."
|
|
645
|
+
: uncertain
|
|
646
|
+
? "Reread get_sender and reconcile before retrying."
|
|
647
|
+
: error.isAuthError
|
|
648
|
+
? error.guidance ||
|
|
649
|
+
"Authenticate again and retry the same scoped request."
|
|
650
|
+
: error.status === 400
|
|
651
|
+
? "Keep each list to 10 entries of at most 3000 characters and 15000 UTF-8 bytes in all, then retry."
|
|
652
|
+
: error.status === 404
|
|
653
|
+
? "Reread list_senders in the explicit workspace and select an existing sender."
|
|
654
|
+
: null,
|
|
655
|
+
});
|
|
656
|
+
}
|
|
657
|
+
return senderContextResult({
|
|
658
|
+
ok: false,
|
|
659
|
+
code: "sender_context_uncertain",
|
|
660
|
+
message: "The sender-context request ended without a confirmed response, so the final state is uncertain.",
|
|
661
|
+
status: null,
|
|
662
|
+
uncertain: true,
|
|
663
|
+
currentUpdatedAt: null,
|
|
664
|
+
guidance: "Reread get_sender and reconcile before retrying.",
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
}
|
|
500
668
|
export async function getSender(input) {
|
|
501
669
|
const api = getApi();
|
|
502
670
|
const requestOptions = workspaceRequestOptions(input.workspaceId);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: first-campaign-onboarding
|
|
3
|
-
description: Help a new Sellable workspace create its first LinkedIn outbound campaign. A yes reply to the welcome starts the existing create-campaign workflow immediately, with DNC and sender setup at the appropriate gates. Send one next-step scheduled reminder for at most 14 days. Use for welcome-thread replies, first-campaign setup, self-serve onboarding, or scheduled onboarding check-ins.
|
|
3
|
+
description: Help a new Sellable workspace create its first LinkedIn outbound campaign. A LinkedIn profile URL (or a yes) in reply to the welcome starts the existing create-campaign workflow immediately, with DNC and sender setup at the appropriate gates. Send one next-step scheduled reminder for at most 14 days. Use for welcome-thread replies, first-campaign setup, self-serve onboarding, or scheduled onboarding check-ins.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# First Campaign Onboarding
|
|
@@ -39,12 +39,29 @@ Classify the run before taking action.
|
|
|
39
39
|
|
|
40
40
|
### Interactive
|
|
41
41
|
|
|
42
|
-
The user is present and can answer.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
The user is present and can answer. The welcome is the thread parent. It asks
|
|
43
|
+
one question, "what's your LinkedIn profile URL?", and says the profile is used
|
|
44
|
+
to research the customer and their company. (A welcome sent before October 2026
|
|
45
|
+
asks "Ready to create your first LinkedIn outbound campaign?" instead; treat a
|
|
46
|
+
reply to either the same way.)
|
|
47
|
+
|
|
48
|
+
A reply in that thread is explicit permission to begin preparation, not
|
|
49
|
+
permission to send. It needs no mention of this Agent.
|
|
50
|
+
|
|
51
|
+
- **The reply contains a LinkedIn profile URL.** Before any tool call, send
|
|
52
|
+
one short line so the customer is not left looking at silence: "Got it.
|
|
53
|
+
Researching you and your company now. I'll be back in a couple of minutes
|
|
54
|
+
with a first campaign to review." Then enter **Create-Campaign Handoff** in
|
|
55
|
+
the same turn, with that URL as the sender identity.
|
|
56
|
+
- **The reply is a yes, or anything else that agrees, with no profile URL.**
|
|
57
|
+
Ask for it once, in one sentence: "What's your LinkedIn profile URL? I'll
|
|
58
|
+
use it to research you and your company." Ask nothing else.
|
|
59
|
+
- **The reply is a question.** Answer it briefly, then repeat the one ask.
|
|
60
|
+
|
|
61
|
+
Do not ask for a second command, a mention, sender connection, DNC list, or
|
|
62
|
+
integrations first. The existing workflow owns intake; do not invent a second
|
|
63
|
+
onboarding questionnaire. Never guess the company name; use it only once the
|
|
64
|
+
profile or the workspace gives it.
|
|
48
65
|
|
|
49
66
|
Use the parent thread to interpret short replies; a yes elsewhere is not
|
|
50
67
|
blanket authorization. Keep replies in the same thread. To start a separate
|
|
@@ -172,7 +189,8 @@ sent separately when the Agent becomes ready; do not repeat it daily.
|
|
|
172
189
|
1. **Invite not accepted:** include the refreshed invite link and ask them to
|
|
173
190
|
join. Do not combine it with a sender/DNC checklist.
|
|
174
191
|
2. **Member present, no draft:** "Want to get your first LinkedIn outbound
|
|
175
|
-
campaign started? Reply
|
|
192
|
+
campaign started? Reply in this thread with your LinkedIn profile URL. I'll
|
|
193
|
+
research you and your company and bring back a first campaign to review."
|
|
176
194
|
Do not block this invitation on a connected sender or DNC list.
|
|
177
195
|
3. **Draft present:** name the most advanced draft and the saved next action
|
|
178
196
|
(for example, approving its brief). Offer to continue it, never duplicate it.
|
|
@@ -186,8 +204,8 @@ approval. Do not repeat multiple safety disclaimers.
|
|
|
186
204
|
|
|
187
205
|
## Create-Campaign Handoff
|
|
188
206
|
|
|
189
|
-
After explicit agreement (
|
|
190
|
-
conversation; do not ask the user to run another command.
|
|
207
|
+
After explicit agreement (a profile URL or a yes in the welcome thread),
|
|
208
|
+
continue in the same conversation; do not ask the user to run another command.
|
|
191
209
|
|
|
192
210
|
1. Call `bootstrap_create_campaign({ flowVersion:"v2", host:<current host> })`.
|
|
193
211
|
2. Load `get_subskill_prompt({ subskillName:"create-campaign-v2" })` to
|