@seldonframe/mcp 1.40.6 → 1.40.8
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/package.json +3 -1
- package/src/tools.js +70 -5
- package/src/welcome.js +27 -18
package/package.json
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seldonframe/mcp",
|
|
3
|
-
"version": "1.40.
|
|
3
|
+
"version": "1.40.8",
|
|
4
|
+
"description": "MCP server for SeldonFrame — AI-native Business OS platform. v1.40.8: HOTFIX — chatbot widget bugs surfaced on the v1.40.7 first-test. Two bugs blocked the just-shipped chatbot embed from actually working end-to-end on Sunset Plumbing. (1) INPUT TEXT INVISIBLE (white-on-white). The .sf-agent-input CSS in embed.js had no explicit color rule, so typed characters inherited the host page's color (var(--sf-text)). On workspaces with stored dark themes OR pages that set color globally, characters rendered white-on-white-background — invisible while typing. v1.40.8 hardcodes color:#111 + background:#fff + -webkit-text-fill-color:#111 on the input element, plus a placeholder color rule. The chat widget is now isolated from host-page CSS — typed characters always readable regardless of host theme. (2) CORS BLOCKING /turn FETCH. The chatbot widget loads as <script src='https://app.seldonframe.com/...'> on workspace subdomain pages (e.g. sunset-plumbing-co.app.seldonframe.com). Script-tag loading isn't CORS-restricted, but the widget's POST fetch from inside the script to https://app.seldonframe.com/api/v1/public/agent/.../turn IS cross-origin. Pre-1.40.8 the turn endpoint returned ZERO CORS headers — browser blocked the preflight, fetch threw, widget surfaced 'Connection issue. Please try again.' on every send. v1.40.8 adds Access-Control-Allow-Origin: * + Methods + Headers + Max-Age, plus an OPTIONS handler for preflight, on every code path of the turn endpoint (invalid_json, missing_message, message_too_long, agent_not_found, agent_not_active, conversation_create_failed, the SSE stream, and the JSON fallback). Origin=* is correct here because the chatbot is intentionally embeddable on any operator's website (the entire point of the embed); the endpoint serves only public, conversation-scoped data; downstream agent runtime already enforces per-conversation auth via conversation_id + anonymous_session_id. Loosening CORS doesn't loosen application authorization. NO new env vars, NO migrations, NO new MCP tools. Backend redeploy required for both fixes (embed.js is server-rendered per-request — operators don't need to re-embed; bubble auto-pulls new CSS on next page load). EXPECTED IMPACT: visit https://sunset-plumbing-co.app.seldonframe.com → typed characters in the chat input are dark gray and readable; sending a message reaches the agent + streams the SSE response back. End-to-end chatbot UX now actually works on workspace subdomains. Caps the v1.40.7 ship.",
|
|
5
|
+
"description": "MCP server for SeldonFrame — AI-native Business OS platform. v1.40.7: WORKSPACE-LEVEL CHATBOT EMBED. The natural-language ask 'add the chatbot to my landing page' now works as a single MCP call. Pre-1.40.7 the only way to put the chatbot bubble on a page was to copy-paste the embed snippet into Pages → Edit (the v1.40.6 banner promised an automated path that didn't actually exist — this fixes that). v1.40.7 ships the real implementation. NEW lib/agents/public-embed.ts: getPublicChatbotEmbed(orgId) reads, setPublicChatbotEmbed(orgId, {embedUrl, agentId}) writes to organizations.settings.chatbot. Storage validates https-only embed URLs as defense-in-depth (the writer only ever derives URLs from WORKSPACE_BASE_DOMAIN, but the read-side check ensures a malformed JSONB value can't inject arbitrary script). NEW components/landing/chatbot-script.tsx wraps Next.js <Script strategy='afterInteractive'> so the embed.js loads off-critical-path. Wired into BOTH /s/[orgSlug]/[...slug]/page.tsx (workspace home rewrite target) and /l/[orgSlug]/[slug]/page.tsx (legacy landing route) — every public page of every workspace honors the embed if set. NEW api/v1/agents POST op 'embed_on_landing' validates agent ownership + status (test/live only — refuses draft) + builds embed.js URL from agent.orgSlug + agent.slug + WORKSPACE_BASE_DOMAIN, then calls setPublicChatbotEmbed. Sibling op 'remove_from_landing' clears the embed without deleting the agent (still serves /agents/[id]/test for sandboxing). NEW MCP tool embed_chatbot_on_workspace_landing({ workspace_id, agent_id }) is the operator-facing one-call wrapper. Sibling remove_chatbot_from_landing({ workspace_id }) clears it. build_website_chatbot's next_steps step 4 updated to reference embed_chatbot_on_workspace_landing as a one-call action (was misleading add_composite_section guidance pre-1.40.7). Welcome banner v1.40.7 section walks through the embed flow with the actual tool name. NO new env vars (uses existing WORKSPACE_BASE_DOMAIN). NO migrations (settings is already a flexible JSONB; new chatbot key merges in cleanly with existing keys). Backend redeploy required for the new API op + page-renderer injection. Pairs with v1.40.6's Custom Agent → Custom Workflow rename for a coherent post-creation operator UX: agents and workflows are now visually distinct, AND the chatbot is one natural-language ask away from being live on the landing page. EXPECTED IMPACT: operator says 'add the chatbot to the Sunset Plumbing landing' → Claude Code calls embed_chatbot_on_workspace_landing → bubble appears bottom-right on https://sunset-plumbing-co.app.seldonframe.com immediately on next page load. Closes the gap between agent creation and agent-on-page that v1.40.6 left open.",
|
|
4
6
|
"description": "MCP server for SeldonFrame — AI-native Business OS platform. v1.40.6: UX FIX — Custom Agent → Custom Workflow rename + clearer chatbot-to-landing embed flow. Two related operator-confusion bugs surfaced after the Sunset Plumbing test. (1) RENAMED 'Custom Agent' template in /automations → 'Custom Workflow'. The /automations page hosts time-triggered + event-triggered workflow rules (Speed-to-Lead, Win-Back, Daily Digest, etc.); /agents hosts persistent AI assistants (chatbots, voice receptionists). They are conceptually different primitives — automations fire on a trigger and exit, agents are always-on with conversational state. The 'Custom Agent' coming-soon placeholder used 'agent' in its name, causing operators to (a) search /automations for their chatbot they created via build_website_chatbot, (b) search /agents for their workflow templates, neither matching expectations. Renamed to 'Custom Workflow' with body copy that explicitly points to /agents for conversational AI. Removes the ambiguity at the source. (2) CHATBOT-TO-LANDING EMBED FLOW now explicit. Pre-1.40.6 the build_website_chatbot success response said only 'Drop on the operator's website: <script ...></script>' which operators interpreted as 'I have to copy-paste this myself' — they didn't realize Claude Code can inject the script directly into the SF-hosted landing page via add_composite_section. v1.40.6 reframes step 4 of next_steps as a TWO-PATH decision: 'Add to the operator's SF-hosted landing page: ask me to add the chatbot to my landing page and I'll inject the script via update_landing_section. (For an external website the operator owns, paste this snippet manually: <script src=...>)'. Plus a NEW section in welcome.js banner that walks through the embed-via-Claude-Code flow explicitly — when the operator asks 'add the chatbot to my landing page' AFTER build_website_chatbot, Claude Code uses add_composite_section to insert a custom HTML section with the embed script. Operators no longer have to find/edit HTML manually. NO new env vars, NO migrations, NO new MCP tools. Backend redeploy required for the /automations rename to take effect. EXPECTED IMPACT: operators searching for their chatbot land on /agents directly (not lost in /automations); operators asking 'how do I add the chatbot to my page' get a one-natural-language-ask answer instead of a copy-paste task. Pairs cleanly with v1.40.5's Unsplash production-compliance ship — both reduce friction in the post-creation operator experience.",
|
|
5
7
|
"description": "MCP server for SeldonFrame — AI-native Business OS platform. v1.40.5: UNSPLASH PRODUCTION-TIER COMPLIANCE + 3-TIER BROADENING. Three coordinated changes that close the loop on Unsplash production approval (raises rate limit from 50 req/hour to 1000 req/hour) and fix the medspa 0-result case v1.40.4 didn't catch. (1) PHOTOGRAPHER ATTRIBUTION rendered on every Unsplash-sourced image. NEW UnsplashAttribution type captures photographer_name + photographer_username + photographer_url + photo_id from each search-result.user payload. New ResolvedUnsplashImage interface bundles { url, attribution } as the resolver's return shape. NEW resolveHeroImage() + resolveGalleryImages() siblings of the legacy URL-only functions return the full payload. enhance-blocks.ts threads attribution into LandingPageSection content (heroImageAttribution on hero blocks, attribution per item on projectGallery). NEW UnsplashCredit component in hero.tsx renders 'Photo by NAME on Unsplash' with both names linking to the photographer's profile + Unsplash homepage with the spec-required UTM params (?utm_source=seldonframe&utm_medium=referral). Tone='light' for cinematic-fullbleed (white text overlaying photo bottom-right corner), tone='dark' for side-image variants (muted text below image). Gallery tiles extend the existing hover overlay with a per-tile credit line. Without this, Unsplash's production-tier reviewers reject the application; with it, every public landing page on every workspace is compliant. (2) DOWNLOAD-LOCATION TRACKING fired on every resolved image. NEW trackUnsplashDownload() helper sends a fire-and-forget GET to photo.links.download_location whenever a hero or gallery image is resolved. Unsplash uses this to credit the photographer's download counter — required by the API guidelines, checked during production review. Failure of the ping logs but doesn't block workspace creation. Critical-path latency unchanged (the GET runs in parallel with the rest of enhance-blocks). (3) THREE-TIER QUERY BROADENING. v1.40.4 dropped the first word on a 0-result; v1.40.5 also tries the LAST 2 words as a third tier. The HERO Aesthetic test surfaced that 'minimalist medspa treatment room' returned 0 even after broadening to 'medspa treatment room' — the word 'medspa' itself is rare on Unsplash (photographers tag spa/wellness/clinic/aesthetic, not 'medspa'). Tier 3 strips niche brand-marketing tokens entirely: 'minimalist medspa treatment room' → 'minimalist medspa treatment room' / 'medspa treatment room' / 'treatment room'. The last tier is universal noun phrasing that's heavily tagged. Per-query hit rate now ~99.5%. NEW buildQueryCandidates() helper deduplicates the three tiers automatically. Mirrored in scripts/test-unsplash.mjs so the diagnostic stays accurate. NEXT STEP FOR OPERATOR: redeploy backend, re-test (5/5 should pass), CREATE one workspace as a real-world demo, then submit for production approval at https://unsplash.com/oauth/applications. The production review form asks for: app URL (your published workspace), app description, screenshots showing photographer attribution + verifying download tracking is firing (Unsplash inspects the API logs server-side). Approval typically lands in 24-48h, then rate limit auto-lifts to 1000/hour. Unsplash API is FREE at every tier — no payment, ever. NO new env vars (uses existing UNSPLASH_ACCESS_KEY). NO migrations (LandingPageSection.content is a JSONB-style record; new optional fields are forward-compatible). Backend redeploy required. Pairs with v1.40.2 onError defenses + v1.40.3 broken-fallback removal + v1.40.4 content_filter relaxation. Belt + suspenders + production approval.",
|
|
6
8
|
"description": "MCP server for SeldonFrame — AI-native Business OS platform. v1.40.4: UNSPLASH HIT-RATE FIX — content_filter relaxed + 0-result retry. Diagnostic test (scripts/test-unsplash.mjs, run before re-creating a workspace) surfaced two real causes of the broken-hero pattern that v1.40.3's gradient-fallback was masking. (1) content_filter=high was blocking legit medspa imagery. 'minimalist medspa treatment room' returned ZERO Unsplash results with content_filter=high; 'serene aesthetic clinic marble' returned 15. The high filter is over-paranoid for professional stock photography (no nudity/violence required to pass). v1.40.4 drops to content_filter=low across both resolveHeroImageUrlForQuery + resolveGalleryImageUrlsForQueries — same safety profile (Unsplash editorial standards still apply), much higher hit rate. (2) Some LLM-generated queries genuinely return 0 results because the leading adjective is too specific. 'minimalist medspa' → 0; 'medspa' → many. v1.40.4 introduces a broadenQuery() helper that drops the first word and retries once if the original returned 0 results. Common-case fix that raises per-query hit rate from ~80% to ~99% without expanding the API budget meaningfully (only fires on misses). Both resolvers now (a) try the original query, (b) on 0-result OR API-error, retry with the broadened query, (c) on second miss, return empty/skip the slot (gradient empty-state still kicks in as last resort, per v1.40.3 contract). Refactored the request-shape into a shared searchUnsplash(query, apiKey, opts) helper so future tweaks land in one place. SECONDARY OBSERVATION: the diagnostic also surfaced that the production Unsplash app is on DEMO TIER (50 req/hour). Each workspace burns 7 image calls; the 50-req cap → ~7 workspaces/hour ceiling. For sustained testing the operator should submit for production approval at https://unsplash.com/oauth/applications (free, ~24h turnaround) which raises the cap to 5000/hour. v1.40.4 doesn't fix this — only Unsplash's review process can — but the WARNING is logged in the test script output. NO new env vars (uses existing UNSPLASH_ACCESS_KEY). NO migrations. Backend redeploy required. EXPECTED IMPACT: a fresh medspa workspace's 7 image queries (1 hero + 6 gallery) now have ~99% hit rate instead of ~80%, so the rendered page shows real photos in every slot rather than gradient fallbacks for the 1-2 queries that randomly missed pre-1.40.4. Pairs with v1.40.3 onError + gradient defenses for true belt-AND-suspenders coverage.",
|
package/src/tools.js
CHANGED
|
@@ -4980,11 +4980,11 @@ export const TOOLS = [
|
|
|
4980
4980
|
`1. Test in sandbox: ${dashboardUrl}/test (chat with the agent before customers do).`,
|
|
4981
4981
|
`2. Run safety evals: open ${dashboardUrl}/evals → Run evals now (8-scenario suite).`,
|
|
4982
4982
|
`3. When ready, publish to live: call publish_agent({ agent_id: '${agentId}', status: 'live' }) — auto-runs eval gate, requires ≥87.5% pass.`,
|
|
4983
|
-
// v1.40.
|
|
4984
|
-
//
|
|
4985
|
-
// to
|
|
4986
|
-
//
|
|
4987
|
-
`4. Add to the operator's SF-hosted landing page:
|
|
4983
|
+
// v1.40.7 — embed-on-workspace-landing is now a real one-call MCP
|
|
4984
|
+
// tool (was misleading guidance in v1.40.6). When the operator asks
|
|
4985
|
+
// to put the chatbot on their site, call embed_chatbot_on_workspace_landing
|
|
4986
|
+
// and the public landing renderer auto-injects the script tag.
|
|
4987
|
+
`4. Add to the operator's SF-hosted landing page (one MCP call): embed_chatbot_on_workspace_landing({ workspace_id, agent_id: '${agentId}' }) — the chatbot bubble appears bottom-right on every public page. (For an external website the operator owns, paste this snippet manually: <script src="${createResult.embed_url}" async></script>)`,
|
|
4988
4988
|
],
|
|
4989
4989
|
};
|
|
4990
4990
|
},
|
|
@@ -5137,6 +5137,71 @@ export const TOOLS = [
|
|
|
5137
5137
|
},
|
|
5138
5138
|
},
|
|
5139
5139
|
|
|
5140
|
+
// ───────────────────────────────────────────────────────────────────────
|
|
5141
|
+
// v1.40.7 — workspace-level chatbot embed.
|
|
5142
|
+
// The natural-language ask "add the chatbot to my landing page" /
|
|
5143
|
+
// "embed this on the website" / "make the bubble appear on every
|
|
5144
|
+
// page" maps to this single MCP call. Wires the agent's embed.js
|
|
5145
|
+
// URL into organizations.settings.chatbot, and the public page
|
|
5146
|
+
// renderer (/s/ + /l/ routes) injects <script src="..." async></script>
|
|
5147
|
+
// automatically. No Pages → Edit, no copy-paste. One call, done.
|
|
5148
|
+
// ───────────────────────────────────────────────────────────────────────
|
|
5149
|
+
|
|
5150
|
+
{
|
|
5151
|
+
name: "embed_chatbot_on_workspace_landing",
|
|
5152
|
+
description:
|
|
5153
|
+
"USE WHEN USER SAYS: 'add the chatbot to my landing page', 'embed this on the website', 'put the agent on every page', 'make the chat bubble appear', 'wire the chatbot to the public site'. " +
|
|
5154
|
+
"Wires a published agent's embed.js URL into the workspace's organization settings. The public page renderer (/s/ + /l/ routes) reads this on every render and injects a <script src='...' async></script> tag near </body>, so the floating chat bubble appears bottom-right on every page of the workspace's public surface — no per-section editing, no manual HTML, no Pages → Edit step. " +
|
|
5155
|
+
"Agent must already be in status='test' or status='live' (call publish_agent first if it's still draft). One workspace = one chatbot at a time; calling this again with a different agent_id replaces the bubble. Pair with remove_chatbot_from_landing to clear it.",
|
|
5156
|
+
inputSchema: obj(
|
|
5157
|
+
{
|
|
5158
|
+
workspace_id: str("Workspace id (bearer workspace)."),
|
|
5159
|
+
agent_id: str(
|
|
5160
|
+
"Agent id from build_website_chatbot's response or list_agents. Must belong to the workspace and be in status=test or live.",
|
|
5161
|
+
),
|
|
5162
|
+
},
|
|
5163
|
+
["workspace_id", "agent_id"],
|
|
5164
|
+
),
|
|
5165
|
+
handler: async (args) => {
|
|
5166
|
+
const ws = args.workspace_id;
|
|
5167
|
+
const result = await api("POST", "/agents", {
|
|
5168
|
+
body: { op: "embed_on_landing", agent_id: args.agent_id },
|
|
5169
|
+
workspace_id: ws,
|
|
5170
|
+
});
|
|
5171
|
+
if (!result.ok) return result;
|
|
5172
|
+
return {
|
|
5173
|
+
...result,
|
|
5174
|
+
next_steps: [
|
|
5175
|
+
`The chatbot is now live on every page of this workspace's public landing.`,
|
|
5176
|
+
`Open the workspace's public URL to verify the bubble appears bottom-right.`,
|
|
5177
|
+
`Conversations will appear in /agents/${args.agent_id}/conversations.`,
|
|
5178
|
+
`To remove: call remove_chatbot_from_landing({ workspace_id }).`,
|
|
5179
|
+
],
|
|
5180
|
+
};
|
|
5181
|
+
},
|
|
5182
|
+
},
|
|
5183
|
+
|
|
5184
|
+
{
|
|
5185
|
+
name: "remove_chatbot_from_landing",
|
|
5186
|
+
description:
|
|
5187
|
+
"USE WHEN USER SAYS: 'remove the chatbot from the landing', 'take the chat bubble off the page', 'unembed the chatbot', 'hide the chat from visitors'. " +
|
|
5188
|
+
"Clears the workspace's chatbot embed setting so the public page renderer stops injecting the script tag. The agent itself is NOT deleted — it's still available via /agents/[id]/test for sandbox conversations and can be re-embedded with embed_chatbot_on_workspace_landing.",
|
|
5189
|
+
inputSchema: obj(
|
|
5190
|
+
{
|
|
5191
|
+
workspace_id: str("Workspace id (bearer workspace)."),
|
|
5192
|
+
},
|
|
5193
|
+
["workspace_id"],
|
|
5194
|
+
),
|
|
5195
|
+
handler: async (args) => {
|
|
5196
|
+
const ws = args.workspace_id;
|
|
5197
|
+
const result = await api("POST", "/agents", {
|
|
5198
|
+
body: { op: "remove_from_landing" },
|
|
5199
|
+
workspace_id: ws,
|
|
5200
|
+
});
|
|
5201
|
+
return result;
|
|
5202
|
+
},
|
|
5203
|
+
},
|
|
5204
|
+
|
|
5140
5205
|
// ───────────────────────────────────────────────────────────────────────
|
|
5141
5206
|
// v1.26.2 — agent debug + observability tools.
|
|
5142
5207
|
// run_agent_evals = manual eval suite trigger (publish auto-runs too).
|
package/src/welcome.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// stripped. `create_full_workspace` is the only workspace-creation
|
|
9
9
|
// path mentioned anywhere in this briefing.
|
|
10
10
|
|
|
11
|
-
export const VERSION = "1.40.
|
|
11
|
+
export const VERSION = "1.40.8";
|
|
12
12
|
|
|
13
13
|
export const WELCOME_MARKDOWN = `# SeldonFrame — create a real Business OS in one conversation
|
|
14
14
|
|
|
@@ -130,24 +130,33 @@ configure_llm_provider + create_agent + publish_agent + update_agent_blueprint.
|
|
|
130
130
|
Then the operator drops the embed snippet onto their site, OR you can
|
|
131
131
|
help them edit a block on the SF-hosted landing page to include it.
|
|
132
132
|
|
|
133
|
-
### v1.40.
|
|
133
|
+
### v1.40.7 — embedding the chatbot on the SF-hosted landing page
|
|
134
134
|
|
|
135
135
|
When the operator says "add the chatbot to my landing page" / "embed it
|
|
136
|
-
on the website" / "make it appear on the page"
|
|
137
|
-
\`build_website_chatbot
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
136
|
+
on the website" / "make it appear on the page" / "put the bubble on
|
|
137
|
+
every page" AFTER \`build_website_chatbot\` returned an agent_id:
|
|
138
|
+
|
|
139
|
+
\`\`\`
|
|
140
|
+
embed_chatbot_on_workspace_landing({
|
|
141
|
+
workspace_id: '<the workspace>',
|
|
142
|
+
agent_id: '<from build_website_chatbot response>'
|
|
143
|
+
})
|
|
144
|
+
\`\`\`
|
|
145
|
+
|
|
146
|
+
That's it. ONE call. The tool stores the embed.js URL on the workspace's
|
|
147
|
+
organization settings; the public page renderer (/s/ + /l/ routes) reads
|
|
148
|
+
it on every render and injects the script tag near </body>. The chatbot
|
|
149
|
+
bubble appears bottom-right on every public page, automatically.
|
|
150
|
+
|
|
151
|
+
Requirements:
|
|
152
|
+
- Agent must already be in status='test' or 'live' (call publish_agent
|
|
153
|
+
first if it's still draft).
|
|
154
|
+
- Workspace bearer must own the agent.
|
|
155
|
+
|
|
156
|
+
To remove later: \`remove_chatbot_from_landing({ workspace_id })\`.
|
|
157
|
+
|
|
158
|
+
The operator should NEVER have to copy-paste a script tag into Pages →
|
|
159
|
+
Edit. One natural-language ask, one MCP call, done.
|
|
151
160
|
|
|
152
161
|
After publish, observability tools the operator can call from Claude
|
|
153
162
|
Code at any time:
|
|
@@ -452,4 +461,4 @@ admin dashboard. Pre-fills their email automatically.
|
|
|
452
461
|
<https://seldonframe.com> · **Discord:** <https://discord.gg/sbVUu976NW>
|
|
453
462
|
`;
|
|
454
463
|
|
|
455
|
-
export const FIRST_CALL_BANNER = `🚀 SeldonFrame v1.40.6 is connected. STEP ZERO: for any workspace task call get_workspace_state({workspace_id}) FIRST — returns workspace identity + integrations status + agents with inline health stats + counts + tailored next_steps in ONE round-trip. Replaces 4-6 progressive discovery calls. ANTI-PATTERNS: don't ls/cat/read .env (SF is hosted, not local files); don't check node/npm versions (irrelevant); don't ask 'is Anthropic key configured?' (state response tells you); don't create a duplicate agent (state response shows existing ones — use update_website_chatbot instead of build_website_chatbot when one exists). Token-budget concept removed in v1.27.9 — ignore stale references. CAPABILITY MAP — pick the right primitive BEFORE exploring tools: (a) "build me a website" → WORKSPACE → create_workspace_v2 + block tools. (b) "add a chatbot to my website / landing page" → AGENT (web chat) → build_website_chatbot (v1.28+ skill bundle: configure_llm + create_agent + publish-test in 1 call; auto-detects ANTHROPIC_API_KEY from env). Drop to primitives (configure_llm_provider + create_agent + publish_agent) only for custom flows. CRITICAL ANTI-PATTERN: chat widgets are NOT blocks. Don't search list_blocks for chat — chat agents are a separate primitive (v1.26+). (c) "auto-reply to inbound SMS/email" → CONVERSATION → send_conversation_turn (one-shot Soul-aware reply, not a website widget). (d) "add hero/services/faq/cta section" → BLOCK → get_block_skill + persist_block. (e) "send campaign email/sms" → MESSAGING. (f) CRM ops → list_contacts/create_deal/etc. CHATBOT CANONICAL FLOW (v1.28+ — 1 call instead of 5): build_website_chatbot({workspace_id, name, faq, pricing_facts, greeting}) → wraps configure_llm + create_agent + publish-test in one call, auto-detects ANTHROPIC_API_KEY from env. Then: operator sandbox-tests at /agents/[id]/test → publish_agent({status:"live"}) auto-runs 8-scenario eval gate (≥87.5% pass required). Observability tools after publish: list_agents, tail_agent_conversations, get_agent_conversation, get_agent_metrics, run_agent_evals, replay_conversation. Dashboard surfaces /agents, /agents/[id]/test, /agents/[id]/settings, /agents/[id]/evals, /agents/[id]/conversations let operators iterate without leaving the browser. WORKSPACE FLOW (legacy reference): create_workspace_v2 → IN PARALLEL for all 7 recommended_blocks (hero, services, about, faq, cta, booking, intake): get_block_skill + persist_block → complete_workspace_v2 → finalize_workspace({workspace_id, email}). Run blocks in PARALLEL (Promise.all) — sequential takes 60+ seconds. v1.10+ CUSTOMIZE: regenerate_block, upload_workspace_image (image_url preferred over base64). v1.11+ STRUCTURAL: get_landing_structure, move_section, delete_section. v1.12+ COMPOSITES: add_composite_section / update_composite_section — manifest ANY block from 12 low-level primitives. Skipping finalize_workspace leaves the operator with no admin login. Every URL is real. NEVER create local files. v1.34+ UI POLISH (smart defaults + optional levers): every published page ships with motion baked in (RevealOnScroll on sections, Stagger on grid blocks, HoverLift on CTAs) — no operator action required. For operators who want to tune intensity: apply_motion_preset({preset: "minimal"|"subtle"|"balanced"|"editorial"}). For operators bringing their own design system: apply_design_md({design_md_content}) accepts the Google Labs DESIGN.md format; import_claude_design_handoff({bundle}) accepts Claude Design's handoff bundle. All three tools are OPTIONAL — surface them only when the operator's vibe asks for it ("make it feel premium", "I have a brand kit", "I just exported from Claude Design"). Never push these on a user who just wants a working site. v1.36+ PROMPT-FATIGUE GUIDANCE: workspace creation typically fires 8–18 MCP tool calls (workspace + blocks + agent + booking + intake + landing). Claude Code prompts on each by default and create_landing_page's Puck schema is verbose JSON the operator should NOT read. DO TWO THINGS to avoid spamming: (1) RECOMMEND THE OPERATOR pick option 2 ('Yes, and do not ask again for seldonframe – <tool>') the FIRST time create_landing_page / persist_block / build_website_chatbot fire — Claude Code caches per-tool autoapprove for the project, the rest of workspace creation runs without interrupting them. Mention this proactively before the flow starts. (2) BUNDLE TOOL CALLS in parallel via Promise.all — never call get_block_skill + persist_block sequentially for 7 blocks; fire them all at once. v1.36+ LANDING-PAGE COMPOSITION FOR LOCAL-SERVICE BUSINESSES: for trades/service businesses (plumbing, HVAC, locksmith, electrician, roofing, towing, dental, salon, mobile mechanic), default to a 10-section composition: navbar → hero (branded gradient empty-state when no photo) → emergencyStrip (sticky brand-colored banner with phone) → trust strip via the Grid block → servicesGrid (per-service cards with price + duration + Book CTA — replaces the SaaS-style pricing block) → benefits (3 differentiators) → process (3-step what-happens-after-booking) → serviceArea (chip cloud of cities/neighborhoods) → testimonials (5+ quotes — placeholder OK pre-launch) → faq → cta → footer. The Pricing block belongs to TIER-based businesses (SaaS, coaches, gyms) NOT per-service businesses — substitute servicesGrid. v1.36.0 added the servicesGrid, emergencyStrip, serviceArea block types — use them when persisting landing pages for trades verticals. The hero block ships a branded-gradient empty state when heroImage is missing; if the operator does not provide a photo, suggest a stock-photo prompt ('your tech truck on a job, sunset shot in Phoenix') so they can drop one in via /landing → Edit later. v1.37.0 GOOGLE MAPS PASTE → WORKSPACE: when the operator pastes a Google Maps business listing (Top Plumbing Experts, ABC Plumbing of San Antonio, etc.), use create_workspace_from_google_paste — NOT create_full_workspace. Same backend pipeline + same finalize_workspace follow-up; the paste-tool's docstring documents the extraction rules (name → bold title, phone → phone-icon row, address → location-pin line, services → categories chip row + 'Services' section deduped, rating + count → '4.7 ★ (950)' element, weekly_hours → 'Monday: 9 AM-5 PM, Tuesday: closed' parsed into canonical {monday:{enabled:true,start:'09:00',end:'17:00'},...} shape). The weekly_hours field flows DIRECTLY into the booking template's metadata.availability, so the operator's actual hours appear on the public /book page on first GET — no separate configure_booking call. 'Open 24 hours' → start:'00:00', end:'23:59'. 'Closed' day → enabled:false. Wrong key shape (e.g. 'mon' instead of 'monday') is silently dropped by the backend and falls back to Mon-Fri 9-5 defaults. NO Google Places API key required — the paste IS the source of truth. v1.36.4 paired fix: the booking page's normalizeAvailability now accepts both 3-letter and full-name day keys, so any legacy rows already in the DB also hydrate correctly. v1.38.3 ADDITIONAL QUALITY BLOCKS: (a) projectGallery — 6-photo masonry of stock photos auto-fetched per service via Unsplash from queries Claude generates inside enhance-blocks; closes the "feels populated" gap that's the single biggest visible difference between a generic SF workspace and a real-business landing page. (b) stickyMobileCTA — fixed bottom-of-screen Call/Book bar, MOBILE ONLY (md:hidden), industry-standard for trades sites with 2-3x mobile booking lift; auto-included whenever a phone is set. (c) testimonial synthesis from Maps paste — when the operator pastes a Google Maps listing that contains review excerpts, Claude Code extracts them VERBATIM into a 'testimonials' field on create_workspace_from_google_paste; backend renders them as-is. NEVER fabricated — if the paste has no review text, the testimonials block is OMITTED from the page entirely (better empty than fake). The testimonials field in the MCP tool input is OPTIONAL — Claude must omit it when the paste doesn't contain real review text. v1.38.0 ATOMIC HORMOZI-QUALITY OUTPUT: every workspace produced by create_full_workspace OR create_workspace_from_google_paste now ships with Hormozi value-equation hero copy + per-business Unsplash photos + scroll-triggered motion baked in — atomically, no follow-up tool calls, no operator action. Pre-1.38.0 the atomic create produced canned 'Welcome to X' copy from personality content templates; only workspaces where Claude Code did the BLOCK-AS-SKILL flow afterward (get_block_skill + persist_block per block) got the rich output. Tirionforge HVAC happened to look great because of that follow-up; atlantic-plumbing didn't get it. v1.38.0 closes the gap by adding Step 12.7 inside the orchestrator: ONE Claude Opus 4.7 call generates hero + servicesGrid + about + benefits + process + faq + cta from src/blocks/*/SKILL.md (the exact same fat skill files Claude Code reads via get_block_skill — single source of truth, no duplication). Output writes to landingPages.sections (LandingPageSection[]), contentHtml/Css get NULLED, route /l/[orgSlug]/[slug] falls through to <PageRenderer> which auto-wraps below-fold sections in <RevealOnScroll>. Hormozi copy + per-business Unsplash + motion all light up at once. EMAIL-FIRST GUARDRAIL UNCHANGED: create_full_workspace + create_workspace_from_google_paste both still RETURN BEFORE THE EMAIL DANCE — operator can't see URLs until they reply with email, finalize_workspace mints the magic admin link + sends the welcome email via Resend. BYOK pass-through: getAIClient checks organizations.integrations.anthropic.apiKey first, falls back to platform ANTHROPIC_API_KEY env. Cost ~$0.10 per workspace, irrelevant since the operator typically supplies their own key. SOFT-FAIL: any error in Step 12.7 leaves the workspace valid (canned-copy Path A intact); never blocks creation. EXPECTED IMPACT: every fresh workspace looks $10k-tier first-shot, no "create workspace then enhance blocks" two-step dance. v1.40.3 IMAGE PIPELINE FOOLPROOFING: removed the deprecated source.unsplash.com keyless fallback from BOTH resolveHeroImageUrlForQuery and resolveGalleryImageUrlsForQueries. Pre-1.40.3 when the official Unsplash API errored or returned no results we fell back to https://source.unsplash.com/{w}x{h}/?{query} — that endpoint is deprecated and now frequently returns broken responses, which were stored verbatim in landingPages.sections and rendered as broken-image icons before the v1.40.2 onError handler eventually flipped state. The HERO Aesthetic Co. test exposed this: hero showed a broken-image icon despite the gallery rendering 4 medspa photos correctly (proving onError wasn't reliably catching deprecated-CDN failures). Fix: never store a known-broken URL. Hero query miss → empty string → branded-gradient empty-state from frame zero (no broken icon ever). Gallery query miss → SKIP that slot → grid auto-reflows to a clean 4-tile composition instead of 6 tiles with 2 broken. Trade-off: workspaces without UNSPLASH_ACCESS_KEY now ship gradient hero + empty gallery (better than broken images). Operators get full control by setting the env var or replacing images post-launch via update_landing_section. ws1-webhook-pricing-fixes branch ships this; redeploy required.`;
|
|
464
|
+
export const FIRST_CALL_BANNER = `🚀 SeldonFrame v1.40.8 is connected. STEP ZERO: for any workspace task call get_workspace_state({workspace_id}) FIRST — returns workspace identity + integrations status + agents with inline health stats + counts + tailored next_steps in ONE round-trip. Replaces 4-6 progressive discovery calls. ANTI-PATTERNS: don't ls/cat/read .env (SF is hosted, not local files); don't check node/npm versions (irrelevant); don't ask 'is Anthropic key configured?' (state response tells you); don't create a duplicate agent (state response shows existing ones — use update_website_chatbot instead of build_website_chatbot when one exists). Token-budget concept removed in v1.27.9 — ignore stale references. CAPABILITY MAP — pick the right primitive BEFORE exploring tools: (a) "build me a website" → WORKSPACE → create_workspace_v2 + block tools. (b) "add a chatbot to my website / landing page" → AGENT (web chat) → build_website_chatbot (v1.28+ skill bundle: configure_llm + create_agent + publish-test in 1 call; auto-detects ANTHROPIC_API_KEY from env). Drop to primitives (configure_llm_provider + create_agent + publish_agent) only for custom flows. CRITICAL ANTI-PATTERN: chat widgets are NOT blocks. Don't search list_blocks for chat — chat agents are a separate primitive (v1.26+). (c) "auto-reply to inbound SMS/email" → CONVERSATION → send_conversation_turn (one-shot Soul-aware reply, not a website widget). (d) "add hero/services/faq/cta section" → BLOCK → get_block_skill + persist_block. (e) "send campaign email/sms" → MESSAGING. (f) CRM ops → list_contacts/create_deal/etc. CHATBOT CANONICAL FLOW (v1.28+ — 1 call instead of 5): build_website_chatbot({workspace_id, name, faq, pricing_facts, greeting}) → wraps configure_llm + create_agent + publish-test in one call, auto-detects ANTHROPIC_API_KEY from env. Then: operator sandbox-tests at /agents/[id]/test → publish_agent({status:"live"}) auto-runs 8-scenario eval gate (≥87.5% pass required). Observability tools after publish: list_agents, tail_agent_conversations, get_agent_conversation, get_agent_metrics, run_agent_evals, replay_conversation. Dashboard surfaces /agents, /agents/[id]/test, /agents/[id]/settings, /agents/[id]/evals, /agents/[id]/conversations let operators iterate without leaving the browser. WORKSPACE FLOW (legacy reference): create_workspace_v2 → IN PARALLEL for all 7 recommended_blocks (hero, services, about, faq, cta, booking, intake): get_block_skill + persist_block → complete_workspace_v2 → finalize_workspace({workspace_id, email}). Run blocks in PARALLEL (Promise.all) — sequential takes 60+ seconds. v1.10+ CUSTOMIZE: regenerate_block, upload_workspace_image (image_url preferred over base64). v1.11+ STRUCTURAL: get_landing_structure, move_section, delete_section. v1.12+ COMPOSITES: add_composite_section / update_composite_section — manifest ANY block from 12 low-level primitives. Skipping finalize_workspace leaves the operator with no admin login. Every URL is real. NEVER create local files. v1.34+ UI POLISH (smart defaults + optional levers): every published page ships with motion baked in (RevealOnScroll on sections, Stagger on grid blocks, HoverLift on CTAs) — no operator action required. For operators who want to tune intensity: apply_motion_preset({preset: "minimal"|"subtle"|"balanced"|"editorial"}). For operators bringing their own design system: apply_design_md({design_md_content}) accepts the Google Labs DESIGN.md format; import_claude_design_handoff({bundle}) accepts Claude Design's handoff bundle. All three tools are OPTIONAL — surface them only when the operator's vibe asks for it ("make it feel premium", "I have a brand kit", "I just exported from Claude Design"). Never push these on a user who just wants a working site. v1.36+ PROMPT-FATIGUE GUIDANCE: workspace creation typically fires 8–18 MCP tool calls (workspace + blocks + agent + booking + intake + landing). Claude Code prompts on each by default and create_landing_page's Puck schema is verbose JSON the operator should NOT read. DO TWO THINGS to avoid spamming: (1) RECOMMEND THE OPERATOR pick option 2 ('Yes, and do not ask again for seldonframe – <tool>') the FIRST time create_landing_page / persist_block / build_website_chatbot fire — Claude Code caches per-tool autoapprove for the project, the rest of workspace creation runs without interrupting them. Mention this proactively before the flow starts. (2) BUNDLE TOOL CALLS in parallel via Promise.all — never call get_block_skill + persist_block sequentially for 7 blocks; fire them all at once. v1.36+ LANDING-PAGE COMPOSITION FOR LOCAL-SERVICE BUSINESSES: for trades/service businesses (plumbing, HVAC, locksmith, electrician, roofing, towing, dental, salon, mobile mechanic), default to a 10-section composition: navbar → hero (branded gradient empty-state when no photo) → emergencyStrip (sticky brand-colored banner with phone) → trust strip via the Grid block → servicesGrid (per-service cards with price + duration + Book CTA — replaces the SaaS-style pricing block) → benefits (3 differentiators) → process (3-step what-happens-after-booking) → serviceArea (chip cloud of cities/neighborhoods) → testimonials (5+ quotes — placeholder OK pre-launch) → faq → cta → footer. The Pricing block belongs to TIER-based businesses (SaaS, coaches, gyms) NOT per-service businesses — substitute servicesGrid. v1.36.0 added the servicesGrid, emergencyStrip, serviceArea block types — use them when persisting landing pages for trades verticals. The hero block ships a branded-gradient empty state when heroImage is missing; if the operator does not provide a photo, suggest a stock-photo prompt ('your tech truck on a job, sunset shot in Phoenix') so they can drop one in via /landing → Edit later. v1.37.0 GOOGLE MAPS PASTE → WORKSPACE: when the operator pastes a Google Maps business listing (Top Plumbing Experts, ABC Plumbing of San Antonio, etc.), use create_workspace_from_google_paste — NOT create_full_workspace. Same backend pipeline + same finalize_workspace follow-up; the paste-tool's docstring documents the extraction rules (name → bold title, phone → phone-icon row, address → location-pin line, services → categories chip row + 'Services' section deduped, rating + count → '4.7 ★ (950)' element, weekly_hours → 'Monday: 9 AM-5 PM, Tuesday: closed' parsed into canonical {monday:{enabled:true,start:'09:00',end:'17:00'},...} shape). The weekly_hours field flows DIRECTLY into the booking template's metadata.availability, so the operator's actual hours appear on the public /book page on first GET — no separate configure_booking call. 'Open 24 hours' → start:'00:00', end:'23:59'. 'Closed' day → enabled:false. Wrong key shape (e.g. 'mon' instead of 'monday') is silently dropped by the backend and falls back to Mon-Fri 9-5 defaults. NO Google Places API key required — the paste IS the source of truth. v1.36.4 paired fix: the booking page's normalizeAvailability now accepts both 3-letter and full-name day keys, so any legacy rows already in the DB also hydrate correctly. v1.38.3 ADDITIONAL QUALITY BLOCKS: (a) projectGallery — 6-photo masonry of stock photos auto-fetched per service via Unsplash from queries Claude generates inside enhance-blocks; closes the "feels populated" gap that's the single biggest visible difference between a generic SF workspace and a real-business landing page. (b) stickyMobileCTA — fixed bottom-of-screen Call/Book bar, MOBILE ONLY (md:hidden), industry-standard for trades sites with 2-3x mobile booking lift; auto-included whenever a phone is set. (c) testimonial synthesis from Maps paste — when the operator pastes a Google Maps listing that contains review excerpts, Claude Code extracts them VERBATIM into a 'testimonials' field on create_workspace_from_google_paste; backend renders them as-is. NEVER fabricated — if the paste has no review text, the testimonials block is OMITTED from the page entirely (better empty than fake). The testimonials field in the MCP tool input is OPTIONAL — Claude must omit it when the paste doesn't contain real review text. v1.38.0 ATOMIC HORMOZI-QUALITY OUTPUT: every workspace produced by create_full_workspace OR create_workspace_from_google_paste now ships with Hormozi value-equation hero copy + per-business Unsplash photos + scroll-triggered motion baked in — atomically, no follow-up tool calls, no operator action. Pre-1.38.0 the atomic create produced canned 'Welcome to X' copy from personality content templates; only workspaces where Claude Code did the BLOCK-AS-SKILL flow afterward (get_block_skill + persist_block per block) got the rich output. Tirionforge HVAC happened to look great because of that follow-up; atlantic-plumbing didn't get it. v1.38.0 closes the gap by adding Step 12.7 inside the orchestrator: ONE Claude Opus 4.7 call generates hero + servicesGrid + about + benefits + process + faq + cta from src/blocks/*/SKILL.md (the exact same fat skill files Claude Code reads via get_block_skill — single source of truth, no duplication). Output writes to landingPages.sections (LandingPageSection[]), contentHtml/Css get NULLED, route /l/[orgSlug]/[slug] falls through to <PageRenderer> which auto-wraps below-fold sections in <RevealOnScroll>. Hormozi copy + per-business Unsplash + motion all light up at once. EMAIL-FIRST GUARDRAIL UNCHANGED: create_full_workspace + create_workspace_from_google_paste both still RETURN BEFORE THE EMAIL DANCE — operator can't see URLs until they reply with email, finalize_workspace mints the magic admin link + sends the welcome email via Resend. BYOK pass-through: getAIClient checks organizations.integrations.anthropic.apiKey first, falls back to platform ANTHROPIC_API_KEY env. Cost ~$0.10 per workspace, irrelevant since the operator typically supplies their own key. SOFT-FAIL: any error in Step 12.7 leaves the workspace valid (canned-copy Path A intact); never blocks creation. EXPECTED IMPACT: every fresh workspace looks $10k-tier first-shot, no "create workspace then enhance blocks" two-step dance. v1.40.3 IMAGE PIPELINE FOOLPROOFING: removed the deprecated source.unsplash.com keyless fallback from BOTH resolveHeroImageUrlForQuery and resolveGalleryImageUrlsForQueries. Pre-1.40.3 when the official Unsplash API errored or returned no results we fell back to https://source.unsplash.com/{w}x{h}/?{query} — that endpoint is deprecated and now frequently returns broken responses, which were stored verbatim in landingPages.sections and rendered as broken-image icons before the v1.40.2 onError handler eventually flipped state. The HERO Aesthetic Co. test exposed this: hero showed a broken-image icon despite the gallery rendering 4 medspa photos correctly (proving onError wasn't reliably catching deprecated-CDN failures). Fix: never store a known-broken URL. Hero query miss → empty string → branded-gradient empty-state from frame zero (no broken icon ever). Gallery query miss → SKIP that slot → grid auto-reflows to a clean 4-tile composition instead of 6 tiles with 2 broken. Trade-off: workspaces without UNSPLASH_ACCESS_KEY now ship gradient hero + empty gallery (better than broken images). Operators get full control by setting the env var or replacing images post-launch via update_landing_section. ws1-webhook-pricing-fixes branch ships this; redeploy required.`;
|