From abbeed151b1ecd7b500489b8cdc8dffce5624bc5 Mon Sep 17 00:00:00 2001 From: Alexgodoroja Date: Tue, 14 Jul 2026 15:12:31 -0700 Subject: [PATCH 1/2] app-store: add Primitive (email for AI agents) card + detail page Adds io.pilot.primitive to the data-driven app store: overrides + 110 methods, the real Primitive logo (green nautilus mark, dark chip), and the Communications category (shared with AgentPhone), whose blurb now covers email too. Pinned first in "New & Updated". Plain twin re-stamped; build + plain-coverage green. --- public/appicons/io.pilot.primitive.png | Bin 0 -> 16729 bytes scripts/gen-apps.mjs | 7 +- src/data/app-methods.json | 442 +++++++++++++++++++++ src/data/app-overrides.json | 54 +++ src/data/apps.ts | 528 ++++++++++++++++++++++++- src/pages/app-store.astro | 2 +- src/pages/plain/app-store.astro | 2 +- 7 files changed, 1029 insertions(+), 6 deletions(-) create mode 100644 public/appicons/io.pilot.primitive.png diff --git a/public/appicons/io.pilot.primitive.png b/public/appicons/io.pilot.primitive.png new file mode 100644 index 0000000000000000000000000000000000000000..a65efd6cd2f456527a312945bca41a958e6a60c9 GIT binary patch literal 16729 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 z z@i_BBLG?zV#fgniCG)tRG!JWRydb-?x7DSzJ&Ywh!*zQmAkAW^R%qlwm-t={f39k; zoH^aaiBHwcOr(c$*hEucEwm(&KR3DlSDc&scg3=a;K<=`0F=JQ#)(&YZS#IX=q#He z0$RKz3g@iq-po$Sci6=WPR>8w*n~m3*_MM3Q%gFI;EcTXV$`0%*t_Nn*?T~0^r-yx1Z>t25rTKE~oSs2onBwYqg+>}4}lHwDc61DmN?5Azr zo0#&!Yx7}a!IGxOQrr4m5mu;f}*&h9oZ1fu*iOx)iSf@ZEoy}?&Ez0}*3=4@!mVw4L z+jD-!L!-~6c!n~g#Fs%^TsF=c5`C*tq9C60590z@gb_JaL_jptK2xh0v{?3*uxsc9 z)=e!0we5iatzrO!IuAL`NI^;l9Vm|~y@ES`? zyxA}Cqc6&;9w=K%ZZiBLpi;pH-@`e31r4k>G&k)DB!)Nin(wZ;Gb?o|Dgo1Cd+);> zU>x6_21A&dhu@o*iL&Enbp-2%sW$p|h->TFCWg77CwqD7(G9Rsi_b>OZgKv?k6A8- zxG-hzve{K(`nnO7IE%^+@EH`I*cf$NOPIzPoZZsDqf}xj#hX z-8Su&5Gq9QrO$e`5U6n|0)m&>{#^1eG|V<0VNSWJp59^b>`H~YaN^@sYpth?934j7 zM=az$*`XAepM?Di-{N%R!JOhr;rGkAeP2El{ z!dkt^=qL5?LNEhc0SWGUH1!|325f%7rg%4*hPL)%*T*KQC5(Lba-31+e2U%671ABD zlj~>$aM>tiPCHh7u5$sWeL;2!Xp3aGXx-&IL#x=|Hp?eV2xNE4!+4w#1dy$ri< z|6pY5E-8w2XLcSOqN(%oE6a9TSp&-c8Z>x#ib+L;?EU(0=@O7}n*?wA~6yLR8Vd*go;w8s_+dCI@)$~k} zy*T7S&mo&Y0Q;*!v%JF=WSR0#bSYC+Q0#~S>yZkPFqlwGctK9$Xl~e9rsdDgHBH;B zRb0skF&vz8@Za+5+nI;jm(QNqkvBB|0a%1?A|PCoTTwfiC}$U`B+X&9W>#mY1iq7v zYUsCvc|T^AES@c@SdlE5Iz+M-qc_Pr7+tXWfP$ISAvj?omYLrw0Ita;1uj!{ijS`$ z4GY_K6o;RlB9qQw{L5h+a*ph_mQ_;6Y+lJzY2~S+gm8nN1mNorMKLpzHNN$v$M|PS zmpEv#@lv_T0D~*{Pdzz?WkT1HAgowN#u;xNZv|NDpfl4OXx8zzVyFiqR4+C7s3}e^ z4lj{d@t4q__{E|5yT&>w_1gI~hhmr%z%z~(SNxJ$D?k41rvb1G%|_LvE=QUVok=&( zL(GPq=RFO!0j^D`86+R>m?_DAV-Jml{^7HNDmYTTQ_?_6z2l}b?K_K(xPHq_gMYm5 zvG1eC7%9rc4U2LAaF0}VM3T$GN|Mr1>iO#|r`+Be0eOR)Eus#c=(2qtSUFIPtx{#a zry&4^Fk@J6_!edv!Hkq<_r7%~Neph|sbkiU?qq|;>qY)YJZrEgOhCLYqmdfrG6{>= z0%m^X`SMrS3kM+ z$M`ebB5<|qEa5l{mS&Eqwc~B>cw7EKPx~~LHxsoVzmQZXM|5PTx@6EUr3)TF>L*M# z!bDEZ^h-0-Fno_=FwQXdSp{o5Vg$Pq>Z7H{8(W62Dg{%7Qu5w*H2>!qU15(;6-s=_ zMlfa@9K?^iX}P0R zjf@KUe&l+Z$E#XB3(`jr>%-3FQ>s<^JF?qz0Bw_E2uhQnE)XI3yLvP#fIw0zplmTj zr^?jN{60(r+?}*jn@MloF7+nsGt>JX-LE{em?{nGG!d)m93adH_NUSEtdmBSg2B);%A}x50wAkQakWqh5!J-VE<<>!2ho0|BKeXNitk!epbAW TFa9?&0U#@>BvCJB67v55nP_{Z literal 0 HcmV?d00001 diff --git a/scripts/gen-apps.mjs b/scripts/gen-apps.mjs index ac24c54a..2e278b13 100644 --- a/scripts/gen-apps.mjs +++ b/scripts/gen-apps.mjs @@ -27,7 +27,7 @@ const CATEGORIES = [ { id: 'infra', name: 'Infrastructure', blurb: 'Containers, microVMs, and deploys — the compute layer for agents.', hue: 30 }, { id: 'security', name: 'Security', blurb: 'Guardrails and firewalls for agents and their inputs.', hue: 5 }, { id: 'finance', name: 'Finance & Payments', blurb: 'Settle value on-overlay and read the markets.', hue: 155 }, - { id: 'comms', name: 'Communications', blurb: 'Give an agent its own phone number — voice, SMS/iMessage, and threaded conversations.', hue: 315 }, + { id: 'comms', name: 'Communications', blurb: 'Give an agent its own phone number or email inbox — voice, SMS/iMessage, email, and threaded conversations.', hue: 315 }, ]; const CAT_HUE = Object.fromEntries(CATEGORIES.map((c) => [c.id, c.hue])); @@ -38,7 +38,7 @@ const CATMAP = { 'io.pilot.smol': 'infra', 'io.pilot.miren': 'infra', 'io.pilot.docker': 'infra', 'io.pilot.aegis': 'security', 'io.pilot.didit': 'security', 'io.pilot.slipstream': 'finance', 'io.pilot.wallet': 'finance', - 'io.pilot.agentphone': 'comms', + 'io.pilot.agentphone': 'comms', 'io.pilot.primitive': 'comms', }; // ---------- icons: brand mark (Simple Icons), line glyph (Lucide), or real logo image ---------- @@ -63,6 +63,7 @@ const ICON_MAP = { 'io.pilot.bowmark': { image: 'png', fit: 'cover', bg: '#0b0b0a' }, 'io.pilot.orthogonal': { image: 'png', fit: 'cover', bg: '#e3e6df' }, 'io.pilot.agentphone': { image: 'png', fit: 'contain', bg: '#26B65A' }, + 'io.pilot.primitive': { image: 'png', fit: 'contain', bg: '#0b0b0a' }, }; function relLum(hex) { @@ -88,7 +89,7 @@ function iconFor(id, hue) { // ---------- presentation config ---------- const APP_IDS = [ - 'io.pilot.agentphone', + 'io.pilot.primitive', 'io.pilot.agentphone', 'io.pilot.postgres', 'io.pilot.duckdb', 'io.pilot.sqlite', 'io.pilot.mysql', 'io.pilot.redis', 'io.pilot.sixtyfour', 'io.pilot.cosift', 'io.telepat.ideon-free', 'io.pilot.plainweb', 'io.pilot.otto', 'io.pilot.smol', 'io.pilot.miren', 'io.pilot.docker', 'io.pilot.aegis', diff --git a/src/data/app-methods.json b/src/data/app-methods.json index b5c88833..8f608918 100644 --- a/src/data/app-methods.json +++ b/src/data/app-methods.json @@ -1,4 +1,446 @@ { +"io.pilot.primitive": [ +{ +"name": "primitive.signup", +"summary": "Provision your own Primitive account and a managed *.primitive.email inbox in ONE call \u2014 no email, no code, no human step" +}, +{ +"name": "primitive.get_account", +"summary": "Get account info" +}, +{ +"name": "primitive.update_account", +"summary": "Update account settings" +}, +{ +"name": "primitive.get_storage_stats", +"summary": "Get storage usage" +}, +{ +"name": "primitive.get_webhook_secret", +"summary": "Get webhook signing secret" +}, +{ +"name": "primitive.rotate_webhook_secret", +"summary": "Rotate webhook signing secret" +}, +{ +"name": "primitive.list_domains", +"summary": "List all domains" +}, +{ +"name": "primitive.add_domain", +"summary": "Claim a new domain" +}, +{ +"name": "primitive.update_domain", +"summary": "Update domain settings" +}, +{ +"name": "primitive.delete_domain", +"summary": "Delete a domain" +}, +{ +"name": "primitive.verify_domain", +"summary": "Verify domain ownership" +}, +{ +"name": "primitive.download_domain_zone_file", +"summary": "Download domain DNS zone file" +}, +{ +"name": "primitive.get_inbox_status", +"summary": "Get inbound inbox readiness" +}, +{ +"name": "primitive.list_emails", +"summary": "List inbound emails" +}, +{ +"name": "primitive.search_emails", +"summary": "Search inbound emails" +}, +{ +"name": "primitive.get_email", +"summary": "Get inbound email by id" +}, +{ +"name": "primitive.delete_email", +"summary": "Delete an email" +}, +{ +"name": "primitive.download_raw_email", +"summary": "Download raw email" +}, +{ +"name": "primitive.download_attachments", +"summary": "Download email attachments" +}, +{ +"name": "primitive.reply_to_email", +"summary": "Reply to an inbound email" +}, +{ +"name": "primitive.replay_email_webhooks", +"summary": "Replay email webhooks" +}, +{ +"name": "primitive.discard_email_content", +"summary": "Discard email content" +}, +{ +"name": "primitive.get_conversation", +"summary": "Get the conversation an email belongs to" +}, +{ +"name": "primitive.list_endpoints", +"summary": "List webhook endpoints" +}, +{ +"name": "primitive.create_endpoint", +"summary": "Create a webhook endpoint" +}, +{ +"name": "primitive.update_endpoint", +"summary": "Update a webhook endpoint" +}, +{ +"name": "primitive.delete_endpoint", +"summary": "Delete a webhook endpoint" +}, +{ +"name": "primitive.test_endpoint", +"summary": "Send a test webhook" +}, +{ +"name": "primitive.list_filters", +"summary": "List filter rules" +}, +{ +"name": "primitive.create_filter", +"summary": "Create a filter rule" +}, +{ +"name": "primitive.update_filter", +"summary": "Update a filter rule" +}, +{ +"name": "primitive.delete_filter", +"summary": "Delete a filter rule" +}, +{ +"name": "primitive.list_wake_schedules", +"summary": "List wake schedules" +}, +{ +"name": "primitive.create_wake_schedule", +"summary": "Create a wake schedule" +}, +{ +"name": "primitive.get_wake_schedule", +"summary": "Get a wake schedule" +}, +{ +"name": "primitive.update_wake_schedule", +"summary": "Update a wake schedule" +}, +{ +"name": "primitive.delete_wake_schedule", +"summary": "Delete a wake schedule" +}, +{ +"name": "primitive.run_wake_schedule", +"summary": "Run a wake schedule now" +}, +{ +"name": "primitive.list_wake_authorizations", +"summary": "List wake authorizations" +}, +{ +"name": "primitive.create_wake_authorization", +"summary": "Create a wake authorization" +}, +{ +"name": "primitive.update_wake_authorization", +"summary": "Update a wake authorization" +}, +{ +"name": "primitive.delete_wake_authorization", +"summary": "Delete a wake authorization" +}, +{ +"name": "primitive.list_wake_dispatches", +"summary": "List recent wake dispatches" +}, +{ +"name": "primitive.list_routes", +"summary": "List recipient routes" +}, +{ +"name": "primitive.create_route", +"summary": "Create a recipient route" +}, +{ +"name": "primitive.reorder_routes", +"summary": "Reorder recipient routes" +}, +{ +"name": "primitive.simulate_route", +"summary": "Simulate routing for a recipient" +}, +{ +"name": "primitive.update_route", +"summary": "Update a recipient route" +}, +{ +"name": "primitive.delete_route", +"summary": "Delete a recipient route" +}, +{ +"name": "primitive.list_deliveries", +"summary": "List webhook deliveries" +}, +{ +"name": "primitive.replay_delivery", +"summary": "Replay a webhook delivery" +}, +{ +"name": "primitive.get_send_permissions", +"summary": "List send-permission rules" +}, +{ +"name": "primitive.send_email", +"summary": "Send outbound email" +}, +{ +"name": "primitive.semantic_search", +"summary": "Semantic search across received and sent mail" +}, +{ +"name": "primitive.list_sent_emails", +"summary": "List outbound sent emails" +}, +{ +"name": "primitive.get_sent_email", +"summary": "Get a sent email by id" +}, +{ +"name": "primitive.get_thread", +"summary": "Get a conversation thread by id" +}, +{ +"name": "primitive.list_functions", +"summary": "List functions" +}, +{ +"name": "primitive.create_function", +"summary": "Deploy a function" +}, +{ +"name": "primitive.get_function", +"summary": "Get a function" +}, +{ +"name": "primitive.update_function", +"summary": "Update and redeploy a function" +}, +{ +"name": "primitive.delete_function", +"summary": "Delete a function" +}, +{ +"name": "primitive.test_function", +"summary": "Send a test invocation" +}, +{ +"name": "primitive.get_function_test_run_trace", +"summary": "Get a function test run trace" +}, +{ +"name": "primitive.get_org_routing_topology", +"summary": "Get the org's function routing topology" +}, +{ +"name": "primitive.get_function_routing", +"summary": "Get a function's current route binding" +}, +{ +"name": "primitive.set_function_route", +"summary": "Bind a route to a function" +}, +{ +"name": "primitive.unset_function_route", +"summary": "Unbind any route from a function" +}, +{ +"name": "primitive.list_function_secrets", +"summary": "List a function's secrets" +}, +{ +"name": "primitive.create_function_secret", +"summary": "Create or update a secret" +}, +{ +"name": "primitive.set_function_secret", +"summary": "Set a secret by key" +}, +{ +"name": "primitive.delete_function_secret", +"summary": "Delete a secret" +}, +{ +"name": "primitive.list_org_secrets", +"summary": "List org-level (global) secrets" +}, +{ +"name": "primitive.create_org_secret", +"summary": "Create or update an org secret" +}, +{ +"name": "primitive.set_org_secret", +"summary": "Set an org secret by key" +}, +{ +"name": "primitive.delete_org_secret", +"summary": "Delete an org secret" +}, +{ +"name": "primitive.list_function_logs", +"summary": "List a function's execution logs" +}, +{ +"name": "primitive.set_memory", +"summary": "Set a memory" +}, +{ +"name": "primitive.get_memory", +"summary": "Get a memory" +}, +{ +"name": "primitive.delete_memory", +"summary": "Delete a memory" +}, +{ +"name": "primitive.search_memories", +"summary": "Search memories" +}, +{ +"name": "primitive.register_payout_address", +"summary": "Register a payout address" +}, +{ +"name": "primitive.list_payout_addresses", +"summary": "List payout addresses" +}, +{ +"name": "primitive.create_email_challenge", +"summary": "Create an email-native payment challenge" +}, +{ +"name": "primitive.create_challenge", +"summary": "Create a payment challenge" +}, +{ +"name": "primitive.get_challenge", +"summary": "Get a payment challenge" +}, +{ +"name": "primitive.pay_challenge", +"summary": "Pay a payment challenge" +}, +{ +"name": "primitive.get_spend_policy", +"summary": "Get your spend policy" +}, +{ +"name": "primitive.update_spend_policy", +"summary": "Update your spend policy" +}, +{ +"name": "primitive.list_declined_payments", +"summary": "List declined payments" +}, +{ +"name": "primitive.list_registries", +"summary": "List the registries you own" +}, +{ +"name": "primitive.create_registry", +"summary": "Create a registry" +}, +{ +"name": "primitive.get_registry", +"summary": "Get a public registry's metadata" +}, +{ +"name": "primitive.update_registry", +"summary": "Update a registry you own" +}, +{ +"name": "primitive.delete_registry", +"summary": "Delete a registry you own" +}, +{ +"name": "primitive.list_registry_agents", +"summary": "List agents in a registry" +}, +{ +"name": "primitive.publish_agent", +"summary": "Publish an agent into a registry" +}, +{ +"name": "primitive.resolve_registry_handle", +"summary": "Resolve a registry handle to its agent" +}, +{ +"name": "primitive.unpublish_agent", +"summary": "Unpublish an agent from a registry" +}, +{ +"name": "primitive.list_registry_requests", +"summary": "List pending publication requests" +}, +{ +"name": "primitive.decide_registry_request", +"summary": "Approve or reject a publication request" +}, +{ +"name": "primitive.define_agent", +"summary": "Define an agent identity" +}, +{ +"name": "primitive.get_agent", +"summary": "Get an agent's public profile by address" +}, +{ +"name": "primitive.list_templates", +"summary": "List function templates" +}, +{ +"name": "primitive.get_template", +"summary": "Get a function template" +}, +{ +"name": "primitive.install_template", +"summary": "Install a function template" +}, +{ +"name": "primitive.get_template_install", +"summary": "Get template install status" +}, +{ +"name": "primitive.send_mail_batch", +"summary": "Send a batch of emails in one request" +}, +{ +"name": "primitive.ask", +"summary": "Ask about Primitive \u2014 NLWeb query (no authentication)" +}, +{ +"name": "primitive.get_health", +"summary": "Service health check" +} +], "io.pilot.agentphone": [ { "name": "agentphone.usage", diff --git a/src/data/app-overrides.json b/src/data/app-overrides.json index a4d647fb..6aa16164 100644 --- a/src/data/app-overrides.json +++ b/src/data/app-overrides.json @@ -1,4 +1,58 @@ { +"io.pilot.primitive": { +"name": "Primitive", +"tagline": "Email for AI agents \u2014 provision a managed inbox in one call, then send, receive, reply, and search real email over one REST API", +"description": "# Primitive \u2014 email for AI agents\n\n[Primitive](https://www.primitive.dev) gives an agent a real, working email identity with **no SMTP credentials, no DNS, and no human in the loop**. `primitive.signup` provisions a free account plus a managed `*.primitive.email` inbox in **one call** (no email, no code). The adapter caches the API key locally under `~/.pilot` and **injects it on every subsequent call automatically** \u2014 the agent never sees, stores, or passes it. Call signup once; everything else authenticates as you.\n\n## What you can do on the free plan\n- **Send** outbound mail, **reply** on-thread, and **batch-send**, with attachments and idempotency keys.\n- **Receive** at your managed inbox: list, get, search, download raw MIME + attachments, and follow conversations. Long-poll for new mail with `?since=&wait=30`.\n- **Filter** inbound mail, register **webhook endpoints**, and read **inbox readiness**.\n- **Primitive Memories** \u2014 durable JSON key-value state across turns, retries, and inbound messages.\n\n## Auth model\nOne step: `primitive.signup`. It mints a `prim_` API key + a provisioned inbox, caches both locally, and the key is injected on every call thereafter. **Idempotent** \u2014 a host that already has a key keeps it. Any method called before signup **soft-fails with exact activation instructions** instead of erroring.\n\n## Requires an upgrade\nFour families are marked in `primitive.help` under a free-plan disclaimer: **Functions** (hosted JavaScript on inbound mail), **Wake** schedules, **x402** USDC payments over email (invite-only), and **custom Domains**. They ship implemented and callable, and return a plan/entitlement error until the account is upgraded at [primitive.dev](https://www.primitive.dev).", +"vendor": "Primitive", +"vendorUrl": "https://www.primitive.dev", +"license": "Proprietary", +"sourceUrl": "https://github.com/pilot-protocol/app-template/tree/main/submissions/io.pilot.primitive", +"homepage": "https://www.primitive.dev", +"version": "1.0.0", +"categoriesRaw": [ +"email", +"communication", +"inbox", +"messaging" +], +"keywords": [ +"email", +"smtp", +"inbox", +"agents", +"mail", +"primitive", +"send", +"receive" +], +"bundleBytes": 5092912, +"installedBytes": 9376865, +"changelog": [ +{ +"version": "1.0.0", +"notes": [ +"Initial release \u2014 Primitive's email API for agents over one byo HTTPS app: 110 methods + primitive.help.", +"Emailless one-call signup (primitive.signup): mints a prim_ API key + a managed *.primitive.email inbox with no email or code; the key is cached locally and injected on every call automatically.", +"Full email lifecycle on the free plan: send/reply/batch, inbound list/get/search/raw/attachments/conversations, threads, filters, webhook endpoints, and durable Memories.", +"Functions, Wake schedules, x402 payments, and custom domains are implemented and marked gated until the account is upgraded." +] +} +], +"minPilotVersion": "1.10.0", +"runtimes": [ +"go" +], +"protection": "shareable", +"publishedAt": "2026-07-14", +"grants": [ +"fs.read:$APP/config.json", +"fs.read:$APP/secrets.json", +"fs.write:$APP/secrets.json", +"net.dial:api.primitive.dev", +"audit.log:*" +], +"inCatalogue": true +}, "io.pilot.agentphone": { "name": "AgentPhone", "tagline": "A real phone number for your agent \u2014 voice calls, SMS/iMessage, and conversations over REST", diff --git a/src/data/apps.ts b/src/data/apps.ts index 55db6f4d..43fdbc6e 100644 --- a/src/data/apps.ts +++ b/src/data/apps.ts @@ -61,12 +61,538 @@ export const categories: Category[] = [ { "id": "comms", "name": "Communications", - "blurb": "Give an agent its own phone number — voice, SMS/iMessage, and threaded conversations.", + "blurb": "Give an agent its own phone number or email inbox — voice, SMS/iMessage, email, and threaded conversations.", "hue": 315 } ]; export const apps: App[] = [ + { + "id": "io.pilot.primitive", + "name": "Primitive", + "tagline": "Email for AI agents — provision a managed inbox in one call, then send, receive, reply, and search real email over one REST API", + "description": "# Primitive — email for AI agents\n\n[Primitive](https://www.primitive.dev) gives an agent a real, working email identity with **no SMTP credentials, no DNS, and no human in the loop**. `primitive.signup` provisions a free account plus a managed `*.primitive.email` inbox in **one call** (no email, no code). The adapter caches the API key locally under `~/.pilot` and **injects it on every subsequent call automatically** — the agent never sees, stores, or passes it. Call signup once; everything else authenticates as you.\n\n## What you can do on the free plan\n- **Send** outbound mail, **reply** on-thread, and **batch-send**, with attachments and idempotency keys.\n- **Receive** at your managed inbox: list, get, search, download raw MIME + attachments, and follow conversations. Long-poll for new mail with `?since=&wait=30`.\n- **Filter** inbound mail, register **webhook endpoints**, and read **inbox readiness**.\n- **Primitive Memories** — durable JSON key-value state across turns, retries, and inbound messages.\n\n## Auth model\nOne step: `primitive.signup`. It mints a `prim_` API key + a provisioned inbox, caches both locally, and the key is injected on every call thereafter. **Idempotent** — a host that already has a key keeps it. Any method called before signup **soft-fails with exact activation instructions** instead of erroring.\n\n## Requires an upgrade\nFour families are marked in `primitive.help` under a free-plan disclaimer: **Functions** (hosted JavaScript on inbound mail), **Wake** schedules, **x402** USDC payments over email (invite-only), and **custom Domains**. They ship implemented and callable, and return a plan/entitlement error until the account is upgraded at [primitive.dev](https://www.primitive.dev).", + "categories": [ + "comms" + ], + "primaryCategory": "comms", + "keywords": [ + "email", + "smtp", + "inbox", + "agents", + "mail", + "primitive", + "send", + "receive" + ], + "version": "1.0.0", + "vendor": "Primitive", + "vendorUrl": "https://www.primitive.dev", + "license": "Proprietary", + "sourceUrl": "https://github.com/pilot-protocol/app-template/tree/main/submissions/io.pilot.primitive", + "homepage": "https://www.primitive.dev", + "methods": [ + { + "name": "primitive.signup", + "summary": "Provision your own Primitive account and a managed *.primitive.email inbox in ONE call — no email, no code, no human step" + }, + { + "name": "primitive.get_account", + "summary": "Get account info" + }, + { + "name": "primitive.update_account", + "summary": "Update account settings" + }, + { + "name": "primitive.get_storage_stats", + "summary": "Get storage usage" + }, + { + "name": "primitive.get_webhook_secret", + "summary": "Get webhook signing secret" + }, + { + "name": "primitive.rotate_webhook_secret", + "summary": "Rotate webhook signing secret" + }, + { + "name": "primitive.list_domains", + "summary": "List all domains" + }, + { + "name": "primitive.add_domain", + "summary": "Claim a new domain" + }, + { + "name": "primitive.update_domain", + "summary": "Update domain settings" + }, + { + "name": "primitive.delete_domain", + "summary": "Delete a domain" + }, + { + "name": "primitive.verify_domain", + "summary": "Verify domain ownership" + }, + { + "name": "primitive.download_domain_zone_file", + "summary": "Download domain DNS zone file" + }, + { + "name": "primitive.get_inbox_status", + "summary": "Get inbound inbox readiness" + }, + { + "name": "primitive.list_emails", + "summary": "List inbound emails" + }, + { + "name": "primitive.search_emails", + "summary": "Search inbound emails" + }, + { + "name": "primitive.get_email", + "summary": "Get inbound email by id" + }, + { + "name": "primitive.delete_email", + "summary": "Delete an email" + }, + { + "name": "primitive.download_raw_email", + "summary": "Download raw email" + }, + { + "name": "primitive.download_attachments", + "summary": "Download email attachments" + }, + { + "name": "primitive.reply_to_email", + "summary": "Reply to an inbound email" + }, + { + "name": "primitive.replay_email_webhooks", + "summary": "Replay email webhooks" + }, + { + "name": "primitive.discard_email_content", + "summary": "Discard email content" + }, + { + "name": "primitive.get_conversation", + "summary": "Get the conversation an email belongs to" + }, + { + "name": "primitive.list_endpoints", + "summary": "List webhook endpoints" + }, + { + "name": "primitive.create_endpoint", + "summary": "Create a webhook endpoint" + }, + { + "name": "primitive.update_endpoint", + "summary": "Update a webhook endpoint" + }, + { + "name": "primitive.delete_endpoint", + "summary": "Delete a webhook endpoint" + }, + { + "name": "primitive.test_endpoint", + "summary": "Send a test webhook" + }, + { + "name": "primitive.list_filters", + "summary": "List filter rules" + }, + { + "name": "primitive.create_filter", + "summary": "Create a filter rule" + }, + { + "name": "primitive.update_filter", + "summary": "Update a filter rule" + }, + { + "name": "primitive.delete_filter", + "summary": "Delete a filter rule" + }, + { + "name": "primitive.list_wake_schedules", + "summary": "List wake schedules" + }, + { + "name": "primitive.create_wake_schedule", + "summary": "Create a wake schedule" + }, + { + "name": "primitive.get_wake_schedule", + "summary": "Get a wake schedule" + }, + { + "name": "primitive.update_wake_schedule", + "summary": "Update a wake schedule" + }, + { + "name": "primitive.delete_wake_schedule", + "summary": "Delete a wake schedule" + }, + { + "name": "primitive.run_wake_schedule", + "summary": "Run a wake schedule now" + }, + { + "name": "primitive.list_wake_authorizations", + "summary": "List wake authorizations" + }, + { + "name": "primitive.create_wake_authorization", + "summary": "Create a wake authorization" + }, + { + "name": "primitive.update_wake_authorization", + "summary": "Update a wake authorization" + }, + { + "name": "primitive.delete_wake_authorization", + "summary": "Delete a wake authorization" + }, + { + "name": "primitive.list_wake_dispatches", + "summary": "List recent wake dispatches" + }, + { + "name": "primitive.list_routes", + "summary": "List recipient routes" + }, + { + "name": "primitive.create_route", + "summary": "Create a recipient route" + }, + { + "name": "primitive.reorder_routes", + "summary": "Reorder recipient routes" + }, + { + "name": "primitive.simulate_route", + "summary": "Simulate routing for a recipient" + }, + { + "name": "primitive.update_route", + "summary": "Update a recipient route" + }, + { + "name": "primitive.delete_route", + "summary": "Delete a recipient route" + }, + { + "name": "primitive.list_deliveries", + "summary": "List webhook deliveries" + }, + { + "name": "primitive.replay_delivery", + "summary": "Replay a webhook delivery" + }, + { + "name": "primitive.get_send_permissions", + "summary": "List send-permission rules" + }, + { + "name": "primitive.send_email", + "summary": "Send outbound email" + }, + { + "name": "primitive.semantic_search", + "summary": "Semantic search across received and sent mail" + }, + { + "name": "primitive.list_sent_emails", + "summary": "List outbound sent emails" + }, + { + "name": "primitive.get_sent_email", + "summary": "Get a sent email by id" + }, + { + "name": "primitive.get_thread", + "summary": "Get a conversation thread by id" + }, + { + "name": "primitive.list_functions", + "summary": "List functions" + }, + { + "name": "primitive.create_function", + "summary": "Deploy a function" + }, + { + "name": "primitive.get_function", + "summary": "Get a function" + }, + { + "name": "primitive.update_function", + "summary": "Update and redeploy a function" + }, + { + "name": "primitive.delete_function", + "summary": "Delete a function" + }, + { + "name": "primitive.test_function", + "summary": "Send a test invocation" + }, + { + "name": "primitive.get_function_test_run_trace", + "summary": "Get a function test run trace" + }, + { + "name": "primitive.get_org_routing_topology", + "summary": "Get the org's function routing topology" + }, + { + "name": "primitive.get_function_routing", + "summary": "Get a function's current route binding" + }, + { + "name": "primitive.set_function_route", + "summary": "Bind a route to a function" + }, + { + "name": "primitive.unset_function_route", + "summary": "Unbind any route from a function" + }, + { + "name": "primitive.list_function_secrets", + "summary": "List a function's secrets" + }, + { + "name": "primitive.create_function_secret", + "summary": "Create or update a secret" + }, + { + "name": "primitive.set_function_secret", + "summary": "Set a secret by key" + }, + { + "name": "primitive.delete_function_secret", + "summary": "Delete a secret" + }, + { + "name": "primitive.list_org_secrets", + "summary": "List org-level (global) secrets" + }, + { + "name": "primitive.create_org_secret", + "summary": "Create or update an org secret" + }, + { + "name": "primitive.set_org_secret", + "summary": "Set an org secret by key" + }, + { + "name": "primitive.delete_org_secret", + "summary": "Delete an org secret" + }, + { + "name": "primitive.list_function_logs", + "summary": "List a function's execution logs" + }, + { + "name": "primitive.set_memory", + "summary": "Set a memory" + }, + { + "name": "primitive.get_memory", + "summary": "Get a memory" + }, + { + "name": "primitive.delete_memory", + "summary": "Delete a memory" + }, + { + "name": "primitive.search_memories", + "summary": "Search memories" + }, + { + "name": "primitive.register_payout_address", + "summary": "Register a payout address" + }, + { + "name": "primitive.list_payout_addresses", + "summary": "List payout addresses" + }, + { + "name": "primitive.create_email_challenge", + "summary": "Create an email-native payment challenge" + }, + { + "name": "primitive.create_challenge", + "summary": "Create a payment challenge" + }, + { + "name": "primitive.get_challenge", + "summary": "Get a payment challenge" + }, + { + "name": "primitive.pay_challenge", + "summary": "Pay a payment challenge" + }, + { + "name": "primitive.get_spend_policy", + "summary": "Get your spend policy" + }, + { + "name": "primitive.update_spend_policy", + "summary": "Update your spend policy" + }, + { + "name": "primitive.list_declined_payments", + "summary": "List declined payments" + }, + { + "name": "primitive.list_registries", + "summary": "List the registries you own" + }, + { + "name": "primitive.create_registry", + "summary": "Create a registry" + }, + { + "name": "primitive.get_registry", + "summary": "Get a public registry's metadata" + }, + { + "name": "primitive.update_registry", + "summary": "Update a registry you own" + }, + { + "name": "primitive.delete_registry", + "summary": "Delete a registry you own" + }, + { + "name": "primitive.list_registry_agents", + "summary": "List agents in a registry" + }, + { + "name": "primitive.publish_agent", + "summary": "Publish an agent into a registry" + }, + { + "name": "primitive.resolve_registry_handle", + "summary": "Resolve a registry handle to its agent" + }, + { + "name": "primitive.unpublish_agent", + "summary": "Unpublish an agent from a registry" + }, + { + "name": "primitive.list_registry_requests", + "summary": "List pending publication requests" + }, + { + "name": "primitive.decide_registry_request", + "summary": "Approve or reject a publication request" + }, + { + "name": "primitive.define_agent", + "summary": "Define an agent identity" + }, + { + "name": "primitive.get_agent", + "summary": "Get an agent's public profile by address" + }, + { + "name": "primitive.list_templates", + "summary": "List function templates" + }, + { + "name": "primitive.get_template", + "summary": "Get a function template" + }, + { + "name": "primitive.install_template", + "summary": "Install a function template" + }, + { + "name": "primitive.get_template_install", + "summary": "Get template install status" + }, + { + "name": "primitive.send_mail_batch", + "summary": "Send a batch of emails in one request" + }, + { + "name": "primitive.ask", + "summary": "Ask about Primitive — NLWeb query (no authentication)" + }, + { + "name": "primitive.get_health", + "summary": "Service health check" + } + ], + "changelog": [ + { + "version": "1.0.0", + "notes": [ + "Initial release — Primitive's email API for agents over one byo HTTPS app: 110 methods + primitive.help.", + "Emailless one-call signup (primitive.signup): mints a prim_ API key + a managed *.primitive.email inbox with no email or code; the key is cached locally and injected on every call automatically.", + "Full email lifecycle on the free plan: send/reply/batch, inbound list/get/search/raw/attachments/conversations, threads, filters, webhook endpoints, and durable Memories.", + "Functions, Wake schedules, x402 payments, and custom domains are implemented and marked gated until the account is upgraded." + ] + } + ], + "grants": [ + "fs.read:$APP/config.json", + "fs.read:$APP/secrets.json", + "fs.write:$APP/secrets.json", + "net.dial:api.primitive.dev", + "audit.log:*" + ], + "bundles": [ + { + "platform": "darwin-arm64", + "bytes": 4787337 + }, + { + "platform": "darwin-amd64", + "bytes": 5194770 + }, + { + "platform": "linux-arm64", + "bytes": 5041983 + }, + { + "platform": "linux-amd64", + "bytes": 5449416 + } + ], + "installedBytes": 9376865, + "depends": [], + "protection": "shareable", + "featured": false, + "real": true, + "inCatalogue": true, + "icon": { + "mode": "image", + "img": "/appicons/io.pilot.primitive.png", + "fit": "contain", + "pos": "center", + "color": "#0b0b0a", + "ink": false, + "file": null, + "hue": 315 + }, + "minPilotVersion": "1.10.0", + "runtimes": [ + "go" + ], + "publishedAt": "2026-07-14", + "updatedAt": "2026-07-14" + }, { "id": "io.pilot.agentphone", "name": "AgentPhone", diff --git a/src/pages/app-store.astro b/src/pages/app-store.astro index 29ca9369..2bff123e 100644 --- a/src/pages/app-store.astro +++ b/src/pages/app-store.astro @@ -17,7 +17,7 @@ const canonicalUrl = 'https://pilotprotocol.network/app-store'; const featured = featuredApps(); const hero = featured[0]; const sideFeatured = featured.slice(1, 4); -const freshPinned = ['io.pilot.didit', 'io.pilot.agentphone', 'io.pilot.orthogonal', 'io.pilot.bowmark', 'io.pilot.miren', 'io.pilot.smol', 'io.pilot.wallet', 'io.pilot.slipstream']; +const freshPinned = ['io.pilot.primitive', 'io.pilot.didit', 'io.pilot.agentphone', 'io.pilot.orthogonal', 'io.pilot.bowmark', 'io.pilot.miren', 'io.pilot.smol', 'io.pilot.wallet', 'io.pilot.slipstream']; const freshExclude = new Set(['io.pilot.postgres', 'io.pilot.docker']); const fresh = [ ...freshPinned.map((id) => apps.find((a) => a.id === id)).filter(Boolean), diff --git a/src/pages/plain/app-store.astro b/src/pages/plain/app-store.astro index 35d00d78..96e8f534 100644 --- a/src/pages/plain/app-store.astro +++ b/src/pages/plain/app-store.astro @@ -1,7 +1,7 @@ --- // Auto-generated by scripts/regen-plain.mjs. Edit the marketing source and re-run. // plain-source: src/pages/app-store.astro -// plain-source-sha256: f34f6eb64dcc76becebab9c0e80e269c8b870e11a778d2bed64b2f22c4212b51 +// plain-source-sha256: 57e7a571fe0f4bd328fce8ef1468cd50f0c7a269e467d5e1497e656d5c5fe112 import PlainLayout from '../../layouts/PlainLayout.astro'; --- From 53bd5aa65cb9dabfd639c907fe7eeb79d68de540 Mon Sep 17 00:00:00 2001 From: Alexgodoroja Date: Tue, 14 Jul 2026 15:34:54 -0700 Subject: [PATCH 2/2] =?UTF-8?q?app-store:=20primitive=20=E2=80=94=20baked?= =?UTF-8?q?=20logo,=20per-method=20examples,=20free/paid=20divider,=20limi?= =?UTF-8?q?ts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Logo: composite the green Primitive mark onto the app-card black (#111110) so the rounded chip melts into the card instead of showing a mismatched dark square. - Detail page: each method now shows an example JSON payload (real filter shape, placeholder values); methods are split into a free group and an "upgrade" group with a divider + per-method reason; new "Plan & limits" section lists every free limit (send 10/hr·50/day, 60 req/min, 1024MB, 1 webhook, per-IP signup cap, reply-only scope). AppMethod gains example/gated; App gains limits. --- public/appicons/io.pilot.primitive.png | Bin 16729 -> 13410 bytes scripts/gen-apps.mjs | 9 +- src/data/app-methods.json | 440 +++++-- src/data/app-overrides.json | 28 +- src/data/apps.ts | 1604 ++++++++++++++++++------ src/pages/apps/[id].astro | 60 +- src/styles/appstore.css | 21 +- 7 files changed, 1638 insertions(+), 524 deletions(-) diff --git a/public/appicons/io.pilot.primitive.png b/public/appicons/io.pilot.primitive.png index a65efd6cd2f456527a312945bca41a958e6a60c9..03f3f94d16324a7dd41a0d1561f45972b376d0cf 100644 GIT binary patch literal 13410 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�p60iykigyAoXGGCJvzu$er%3RgiE)y7z8Co9Ef{<=%QGk{Aul;g^he7>aKuwZueGbd=pf@ojc!#1+Dh3nPd|6es=?sv5(HhTz`x0IFP3ZtdPUX+^ ztxQgR!uYT!wiT-AN}fX#b}7*AoSJ;=JA*-<1RIDHFc8S?1Ym6Trh^z9l7A{d9=D39G(fYUwINUa6dxr>SYF;AC#4qi$g7Mn@=K$;~{( z@l=VlVASoz;lQjC?CG(37^<-6>U--e+O?J5O=eEw`E^M)Di$bhP1$FT))Y^;_L%;v zbp^va0#8`KY|}zE@>pNOW!Qn36$bl5MUsDzpo4R7b-i!Vk>t_|vgic)fliicl?u->bf*eF$5=aZ6lwFA)0J783+)O1DWJcC*XeMlDE{<3LJOU`W3xu`f6& zPyTU)={H5llK|^eI`Id#JpXVCe3KZJARYk%ILROFG|!BG0Bj2H4*=3JnF#+V-y~8( zTcsw~L`JgtanAfSe=04{EUJ-ct}*PEHLpVKuk8&TzEOmPOS>pNsoYLLOQQJM+x%jx z2&l5C=J0-e(RW5AofT|}yuj2+Udu$jkUk8VmCc82VEn;hCbHKTlB*w)aa&H0pvE#9 z-BU?4>m~QE*~rM}V35vaQ5`4| zE2!+QrHlMBeYMz=G4Pt7MyLIhWfhmV2{>LUX7OL=UvImHVO2 z?cH~gQiB5$VdF3(=ElQBQNJ6+*h!NSBf~_!f)6|PUuKYNeB}D5Xu4_W`!toDG?l$H zwK)p4v}c4o7bSZi4hyB^ZIF4mtL-vWHRWh8sodglh7g-(2}|>8)eW@i6#mPaZfxVg z2l$I1(#u(Dv*Ty1EYDUzKT&nNWkmKZO3}r(FYc$xZLJ)xeh>n3U{rmO?O;j7Ec3mk z*3_b@noKwugZW@PjPz@M{4!69rk&NzdW(dZuu^uEld4F@VFAwj#k8`A-KG8ts$8{o z-G-wn+@x}pH->!pgu(&Y#T`@gJI17InVUA+7dC3gK58Sa^efoiE6RJ-ct zGJ785*ikN_Dhvv2rR7J)0#pL%0g$K|y`c+OlDu_kcGG|DbdPxon1Ufi&V=T-iCAC5 zSWX-+5Q@K<4`42GWO>I>546Ob@iOzDR08>o+{fT|BNmAMd!fAEu^Oslf*p$}W+-$G zbt5psfSKIX486migM{ukVA^j19^>szu>q4)d=vTz2S}E8*ft!b7myyF*1$(?M7}Us z-bH6-fl-KRinOw0k5jj&n!8g>MCoa9vQwjGD`*c79}uM;jh9hXFr}u%P@p81scgT( z(qRL1r#~RMewhBzPE}1G)>8sB-CJ~t%mg_8MRX4EXbn9w9OJ7vjgEi(7=@n;^0gkdJs}g#Ti11cRTvE5H{by} z0mqS%_EJzzo0 zd<43V!RdV>UmH#BgcMQCX6r^@Gy?|>vB`Dg5<~dzuBDQAzPK4A$lC#|sEi5;tOeH%UUV2ZiI3y7Xp4iVK zgsr_S!66&OliU`rb&=k|QE>}nQv^Z}g)|Yo5<)|y@Br6Jp_7TFTp)fD#NVZ1p zc8CDGr1{>PhY*GThSq16o5TCZ7nL376``K(kD><2Q)OSI-CF-)y6O!shTlD>-<5{F z^x)z1#hBJZ4)&s=?nXoZcCx-<;r#(e_#W2~$gF||jC*Ad@+chU798gkL@SudD!}Dk zXBLkeedCzVT0wrn!)*J_f1uFc|_3o@XZ@Z57RM$7zi7KpQx1HkJE-CytDI*)TJoZbw#GS+T6HJ*)fNzmg?&C zI9)j#%G$&E=OT^veMyO=9`3imhWK~rdy~fq^ZeTTi5{m`ql!1no z^$oF_E(ufo#}H|MS)*MNGd;q_x@Hfy4e#q3oJX}j@%VQT{va;$43Bj{kl8*%>;APH zK$POY1!uU07v&z`x1ja6S3Uv(hfLrar{$he&OZ`N<_74Hi1QAoA>A`ibX~slj`AFx zW@J5H1vkTEZ!0P^$l3p5VOtAC5O5qJyB{BGbT;b=ef4(61DyGXoCj3AQYF@LA1I#r zvDA?Cw%MNVeLsBN3?W6o7njvll+u}Bz!W|^kZuJ)RGbF2@>yNQVSm9)tww@P z2Jxo5)nS)GV+m$+KYST0ZXU(rezAaWKHGu-&b%rvWGc6r*yso>ej8&9f zf#EqyQ$O0ng2V6QWFY-xe@!@}F&fMb4EXA6a+SHlp6IIag$9>?eV&1Xw+o537dR>0 zXtM{-rRctWb>yO`j}>(~H3D|Q4lHG{FR?f<;A9rD4C76%{IErg7wRjb43xJJ>0&@4 zcNtQ+9>g%{+sqiC3o}uzsl?AxmU$^SVnLy*0ZGUbNp}nLnZtsk zb8lADPc_t6HTW}4>~U-G)8Ry_cL2pdm+XV$g>qKdwRF0!eSnDL4V6gMx#F%%N>(et zQFw>B+CFc^*ux%)G_Igy-;wdp!gnJPTOrGW#t(oeVca2pa)-r_*!YR^=?+#`hw0|7 zJK5zqx^pS*CUhcq`I_v2y4Os};DC15jBd6$QTFq|rm5>ym<})BDORJS z2+~7pucN|^{(J|enalc7k|87GPMpE(8Fc@C*n@gW!M9aN-RqxI<@3ON02!qn!H)>D%bg%hz=RW1{ zD~C{dKOo?JQwR8^&AVmudxgyL3!Y=m?PHZW#VI)^>;rryseYmV9Z(UQ_kk=0NR$zj zE(BzWfA8MdUU$micY8$eI3zdk1w-Sbg7~Hs&v|A`1+YawOJD*}JX~E8hyiDUrAoWx ziMyc{4v7;EDwRJnJCX{_=SVK?7TBL8;g+E^J^g7w!)iun^mOh)myIhUT$_x+fBl@f zMb9DhQ76(<^h`df6ZoVzi^|VO^!v=3Q$mn}^BH5H&SgB=Zppn=MbjJKNts})$G3Lo z>1|bKfZCX-mhPDuD0m`2jjjdkbxgJ&i>||ZllA%4XU8~rph931%rJg`HmjG3goTK=0%FS8o%GijdY(cO<>y#+g1j8EdWy9q03ZQR8bY}T%0a^D%p zN-cLC9*7_@0aZ+R>6&trbY*HU`DcN#D=I`NLiuMp9@o!!;j zt42@#=}j;Fm6|4d881T#H)K^+^VU%L)Xau4+H57YZAR)ox_VsAWu~*sla>{isw^+{ zm0;WGczN|iq}j@U+#ytmOz_>K2HI7k-FrKowYsX0zYS4W^8Hp828Hrcw_ycNn?SkM zbvtl_P#h7G!_8%K)5>e+?YcHy`xOMV$UtK#r_)UNQiplGmk#wijQF%m@9v&rRxCp* zSbA8FlC08AZ;7|kI$MSJq_wUgO$c;VMTU#ZvS)w}fqdR}7%Y0T%*$`78&m0%)b62m z#L@_zrx%_YeCkE6{^#F={o3~cHu{jS3FV#i^s2&Ze^;w9$g+XGYOdVJ`%o9 zG{Y0x4xd8RySI5G^#&>tL6fd8bXDBXR_{F0&UKGQPgE9^vDLUsxb||RM&S7rkLEQD zV6BD>erYlzj;92MaHf&fgfeMh;$JT#;74fhL__|dZlX0kh1TwnR0m940a+n}(}d

T5VQulDt7?PND@$_oF-D)2)4L7Bw7oyF_UrWbdY#3i`>V9k(esE?2 zPBsqP+sUlYrL{Ju|B)p_6`%qpW&8vtCwT|}nSgOpA^bq{5HRUzE^FtJ*wWjhWOA`2 za8g<$z-B<|0ddAMexiq1N-m06Jm)Sg)SljBuiGVlosVs$U^ zB0!v6kbHk-(Mp0e6sL_j#V=)?SH`$o)R=(mH0Pfg%kJisyeup~|Iklt*q-y48qsi`?!z4X<1dHL~ zEGA}~(bHYfHUEV^&qWXIMUTu3`sD7Z6ut4;oE(#rd<*H>NAz+Rw-C~27?3;s*4lx1 z`p*q~PZgq58--))S;t2`_}YrYIh->m1&n|4OoRyYQMI ziA7fVQ2&X_j`Ldn_IBSH1igh1`>R{`P`BwNtTRc;j6Gah9MvTZUR8kqesdOJ5i`^$`v5c02qAcTadJaYK)jUc(1zAe4;A^$@zW>Ou$^HqH z+nDINbdg-#mpa>~8GfjS2>pTw1Ww&xq3=%6b(8e#ED#u-%O^hI@z_XUwP(e{)zt-q zTRLupPP^0ncV=%eBIZ95TI1cl|F6>d(*|oZD_v}}+h0c>VvIZvCQJi2R4`WUj2sP)gfT)sU~K9$n!`z8K~4d*omIWmA={;SU?! z?Jc3oQd*g_QUOf9x~(cEZ{Vr1j~dTTJBpQsU?72@H0CXW^^m(oD6VTLWc$a1KHZe; z=3C)fsH~u<^A=kNsO=H3xJu4rp^Y$6Mk9?}{VsaRYr$aq@F=Kkm^x>8$X3+MBBJ&(-6MW6C|5mSF3gOVc}&=7_$J+mPtov1vtB9^8w`vuHWtA}Wo32<2ZqzM zUA4NSS@F>5z^tmt;@XqXZeG}@!6WD+21CB4%rz&^6tWh8Q+sP&qM+yvJfUr&iL1zq zgq&>>@ODO`KFjkcqI|~Yl7j~_TRs1jhpy6^ofTBt+sX9Tap~RY)dsTE`id`Jv%JB` zXh-=*%@SuFAy1#e=DRqnOVi*R2~u}#ydMOxht!b)IfH)5A~dBSx>boysIP&mlac}< zvC?r#E_;QJ0c}$(h<{kx&eSw+ki+<-%=0PD@`+jXpS~E>+Z{El=F^)z4=90)SMnL# z%Efds?W7VG=+7h5fcvGp?Zhxg3+QAGS_`Q^Fx8!h;pN9>1ky&PRkt#Dh)gK}o6I>~ z1PCGL;M>C94^g)Nf}dLihiu=-oTB++yp8|4jR>(=u*ZNvnBT`Gl5CfXlm}^Y{PjSI zJ3L2s(;kKjAe5v=m>E8ic?dIj0$D7agcUqV=xR(+k~&yV$x~U$QNN@;t+hEXkNH%1ZT@)FIQ`(!;>q)-V zIqd5477mxJBIVNKoB{uZytU!2+ib-8t-bx?(vob>hBq}LFaSPGF`w~`!g@Y3U0{-{ zqk^s=a33zy2W!e(WaM|9n!}24SP#N)p#n5w7Q>$`h4ZP9^E;{;7dg7HZslw$^V`_; zo1C*q!)pTlNAgYnVh8PcFRUy5#>G_iu70clz7Ks#7m+2LB{%Y?9g-=yXz_Xl&3c+Q z<94zVXK{A%fZDAWXtSUoF=b+HS89#MXOe++E8z4Z8s`U@#Ng;l`BteX@*M<9!2CQ0 zyBowzZ^1~i7%>2;|0crcE}k`1bi*rTqdQsq^H7Vd*19_Zd{$s`mSYaP{0)SeqgD&y&q+>B`PE7%21eEL)t3NejSZ_=#jETi3oWVYZTSCizm`ntPhqc z_bGP{$(+D=rLgsZ`f_caZWioF6D?>yh;0O%=0s+^h|bWscsX1Tl839m$^Z{$U^yHp z=wyhg=*^@1fUQ6Ks2U|+WUp`bCn5oCp{)Zj?BlR?iX|+D+mn?C#6+i$pfmN2mda=+ z=Qc;0PUJ-w_GqGiMATona3z`>LK$jt&@yo6*Y^}@&7kRTIfB1q3pW={ zp)C&?Z_p@wTa_7Sl;R#+?j9GeIXf1uGrWm-GAQ3fS>qeYTWB4|SoSD~@FiJ^2SnD) zZ87LJ_^QY%?R1y8&(Z}EEYN|Y7RDrybg5L3mAQ<$?V=xOuXdqj#rOQvvRc7a=aS?y z*?N-L2hiw0T{!bZJjUzzoJ5TC zsHr;`0tn*?p+!nP!e02iMqY=_4wDw|Ka;weVow8^bKRaN03!ExUL$_m8=*CKC5wLp zN*3$ywG|*EmPYNZ%DhtfCxq+Hh_f}*R=kSad6FZl?Xs3Od%NsZIqCBM*}-0Knfv5v zP8=V3o3+$3M}sg&g+q?^qFfECO#M;=MvIrBIwL_tUfRaoRNf`(1w#J=71SJMtxbY# zpQgyCIIIOoeI8MjEsC=+@4qs0;S`570y_0Owey6} za>xVj@_SP6udemZS_vMdjfLE5W66!yqC2?THHx3E)W5!65IpOzU>`{w9I5Ywv0t-> zxzpx^#S437tP1942+A)0sjcE9h{u82A^0cISY0sfc*F0*hh`bD@OKguMJS#7@F5;a zvw{=j0;AJkJOl-Y!;NE4%FjM0K^s|Erx$V4nx4fH9@tLd94`(u|8XyxqHGheK^UhE z8Erk*`wfrs3!x)^s}QEb-S`XC?ioP|bJp)UAUFZhNKGZV+l; zTdR-$a>6Npwq*fN@JPM7c@ksSJQ_ERa-PAl{;k)i55$jC)Pw-}bMyOTH-!h8;+XC5b=0fk0_f@6LO9WC9 z+X?(RH@fr1E7nElIA8f=$Wn9JmD>CQD2B*T_!T|+P5iDh>`!ibt85}G`kokf@-L!){w$@ zl9BZQwYpOrrJ!swg7V0a+PzfTUolPqe_cdP{{H&ww8>67z*Yyl$>5tp6kmU0P-uM- zt?32wAHI<#Hl1)xL>`ru+fA52W9=BK;In-YW1We=ŪGkyq*#lF3#nr0fMb7cMN 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 z z@i_BBLG?zV#fgniCG)tRG!JWRydb-?x7DSzJ&Ywh!*zQmAkAW^R%qlwm-t={f39k; zoH^aaiBHwcOr(c$*hEucEwm(&KR3DlSDc&scg3=a;K<=`0F=JQ#)(&YZS#IX=q#He z0$RKz3g@iq-po$Sci6=WPR>8w*n~m3*_MM3Q%gFI;EcTXV$`0%*t_Nn*?T~0^r-yx1Z>t25rTKE~oSs2onBwYqg+>}4}lHwDc61DmN?5Azr zo0#&!Yx7}a!IGxOQrr4m5mu;f}*&h9oZ1fu*iOx)iSf@ZEoy}?&Ez0}*3=4@!mVw4L z+jD-!L!-~6c!n~g#Fs%^TsF=c5`C*tq9C60590z@gb_JaL_jptK2xh0v{?3*uxsc9 z)=e!0we5iatzrO!IuAL`NI^;l9Vm|~y@ES`? zyxA}Cqc6&;9w=K%ZZiBLpi;pH-@`e31r4k>G&k)DB!)Nin(wZ;Gb?o|Dgo1Cd+);> zU>x6_21A&dhu@o*iL&Enbp-2%sW$p|h->TFCWg77CwqD7(G9Rsi_b>OZgKv?k6A8- zxG-hzve{K(`nnO7IE%^+@EH`I*cf$NOPIzPoZZsDqf}xj#hX z-8Su&5Gq9QrO$e`5U6n|0)m&>{#^1eG|V<0VNSWJp59^b>`H~YaN^@sYpth?934j7 zM=az$*`XAepM?Di-{N%R!JOhr;rGkAeP2El{ z!dkt^=qL5?LNEhc0SWGUH1!|325f%7rg%4*hPL)%*T*KQC5(Lba-31+e2U%671ABD zlj~>$aM>tiPCHh7u5$sWeL;2!Xp3aGXx-&IL#x=|Hp?eV2xNE4!+4w#1dy$ri< z|6pY5E-8w2XLcSOqN(%oE6a9TSp&-c8Z>x#ib+L;?EU(0=@O7}n*?wA~6yLR8Vd*go;w8s_+dCI@)$~k} zy*T7S&mo&Y0Q;*!v%JF=WSR0#bSYC+Q0#~S>yZkPFqlwGctK9$Xl~e9rsdDgHBH;B zRb0skF&vz8@Za+5+nI;jm(QNqkvBB|0a%1?A|PCoTTwfiC}$U`B+X&9W>#mY1iq7v zYUsCvc|T^AES@c@SdlE5Iz+M-qc_Pr7+tXWfP$ISAvj?omYLrw0Ita;1uj!{ijS`$ z4GY_K6o;RlB9qQw{L5h+a*ph_mQ_;6Y+lJzY2~S+gm8nN1mNorMKLpzHNN$v$M|PS zmpEv#@lv_T0D~*{Pdzz?WkT1HAgowN#u;xNZv|NDpfl4OXx8zzVyFiqR4+C7s3}e^ z4lj{d@t4q__{E|5yT&>w_1gI~hhmr%z%z~(SNxJ$D?k41rvb1G%|_LvE=QUVok=&( zL(GPq=RFO!0j^D`86+R>m?_DAV-Jml{^7HNDmYTTQ_?_6z2l}b?K_K(xPHq_gMYm5 zvG1eC7%9rc4U2LAaF0}VM3T$GN|Mr1>iO#|r`+Be0eOR)Eus#c=(2qtSUFIPtx{#a zry&4^Fk@J6_!edv!Hkq<_r7%~Neph|sbkiU?qq|;>qY)YJZrEgOhCLYqmdfrG6{>= z0%m^X`SMrS3kM+ z$M`ebB5<|qEa5l{mS&Eqwc~B>cw7EKPx~~LHxsoVzmQZXM|5PTx@6EUr3)TF>L*M# z!bDEZ^h-0-Fno_=FwQXdSp{o5Vg$Pq>Z7H{8(W62Dg{%7Qu5w*H2>!qU15(;6-s=_ zMlfa@9K?^iX}P0R zjf@KUe&l+Z$E#XB3(`jr>%-3FQ>s<^JF?qz0Bw_E2uhQnE)XI3yLvP#fIw0zplmTj zr^?jN{60(r+?}*jn@MloF7+nsGt>JX-LE{em?{nGG!d)m93adH_NUSEtdmBSg2B);%A}x50wAkQakWqh5!J-VE<<>!2ho0|BKeXNitk!epbAW TFa9?&0U#@>BvCJB67v55nP_{Z diff --git a/scripts/gen-apps.mjs b/scripts/gen-apps.mjs index 2e278b13..c0794c63 100644 --- a/scripts/gen-apps.mjs +++ b/scripts/gen-apps.mjs @@ -63,7 +63,7 @@ const ICON_MAP = { 'io.pilot.bowmark': { image: 'png', fit: 'cover', bg: '#0b0b0a' }, 'io.pilot.orthogonal': { image: 'png', fit: 'cover', bg: '#e3e6df' }, 'io.pilot.agentphone': { image: 'png', fit: 'contain', bg: '#26B65A' }, - 'io.pilot.primitive': { image: 'png', fit: 'contain', bg: '#0b0b0a' }, + 'io.pilot.primitive': { image: 'png', fit: 'cover', bg: '#111110' }, }; function relLum(hex) { @@ -113,7 +113,7 @@ function build(id) { const o = overrides[id] || {}; const cat = CATMAP[id]; const platforms = o.platforms || (LINUX_ONLY.has(id) ? ['linux-arm64', 'linux-amd64'] : ALL_PLATFORMS); - const methods = (methodsMap[id] || []).map((m) => ({ name: m.name, summary: m.summary || null })); + const methods = (methodsMap[id] || []).map((m) => ({ name: m.name, summary: m.summary || null, example: m.example || null, gated: m.gated || null })); return { id, name: o.name || id, @@ -143,6 +143,7 @@ function build(id) { runtimes: o.runtimes || ['go'], publishedAt: o.publishedAt ? String(o.publishedAt).slice(0, 10) : null, updatedAt: o.publishedAt ? String(o.publishedAt).slice(0, 10) : null, + limits: o.limits || null, }; } @@ -150,7 +151,8 @@ const apps = APP_IDS.map(build); const banner = `// AUTO-GENERATED by scripts/gen-apps.mjs from authoritative catalogue snapshots\n// (src/data/app-overrides.json + app-methods.json). Do not edit by hand.\n// No ratings or install counts — those are not published by the catalogue.\n`; const body = `${banner} -export interface AppMethod { name: string; summary: string | null; } +export interface AppMethod { name: string; summary: string | null; example: string | null; gated: string | null; } +export interface AppLimit { label: string; value: string; } export interface AppChangelog { version: string; date?: string | null; notes: string[]; } export interface AppBundle { platform: string; bytes: number | null; } export interface AppDependency { id: string; reason: string; optional?: boolean; } @@ -166,6 +168,7 @@ export interface App { featured: boolean; real: boolean; inCatalogue: boolean; icon: AppIcon; minPilotVersion: string; runtimes: string[]; publishedAt: string | null; updatedAt: string | null; + limits: AppLimit[] | null; } export interface Category { id: string; name: string; blurb: string; hue: number; } diff --git a/src/data/app-methods.json b/src/data/app-methods.json index 8f608918..10c45dfd 100644 --- a/src/data/app-methods.json +++ b/src/data/app-methods.json @@ -2,443 +2,663 @@ "io.pilot.primitive": [ { "name": "primitive.signup", -"summary": "Provision your own Primitive account and a managed *.primitive.email inbox in ONE call \u2014 no email, no code, no human step" +"summary": "Provision your own Primitive account and a managed *.primitive.email inbox in ONE call \u2014 no email, no code, no human step", +"example": "{}", +"gated": null }, { "name": "primitive.get_account", -"summary": "Get account info" +"summary": "Get account info", +"example": "{}", +"gated": null }, { "name": "primitive.update_account", -"summary": "Update account settings" +"summary": "Update account settings", +"example": "{\"spam_threshold\": 10, \"discard_content_on_webhook_confirmed\": true}", +"gated": null }, { "name": "primitive.get_storage_stats", -"summary": "Get storage usage" +"summary": "Get storage usage", +"example": "{}", +"gated": null }, { "name": "primitive.get_webhook_secret", -"summary": "Get webhook signing secret" +"summary": "Get webhook signing secret", +"example": "{}", +"gated": null }, { "name": "primitive.rotate_webhook_secret", -"summary": "Rotate webhook signing secret" +"summary": "Rotate webhook signing secret", +"example": "{}", +"gated": null }, { "name": "primitive.list_domains", -"summary": "List all domains" +"summary": "List all domains", +"example": "{}", +"gated": null }, { "name": "primitive.add_domain", -"summary": "Claim a new domain" +"summary": "Claim a new domain", +"example": "{\"domain\": \"\", \"confirmed\": true, \"outbound\": true}", +"gated": "requires a custom domain whose DNS you control \u2014 the managed *.primitive.email inbox needs no domain setup" }, { "name": "primitive.update_domain", -"summary": "Update domain settings" +"summary": "Update domain settings", +"example": "{\"id\": \"\", \"is_active\": true, \"spam_threshold\": 10}", +"gated": null }, { "name": "primitive.delete_domain", -"summary": "Delete a domain" +"summary": "Delete a domain", +"example": "{\"id\": \"\"}", +"gated": null }, { "name": "primitive.verify_domain", -"summary": "Verify domain ownership" +"summary": "Verify domain ownership", +"example": "{\"id\": \"\"}", +"gated": "requires a custom domain whose DNS you control" }, { "name": "primitive.download_domain_zone_file", -"summary": "Download domain DNS zone file" +"summary": "Download domain DNS zone file", +"example": "{\"id\": \"\", \"outbound_only\": true}", +"gated": "requires a custom domain whose DNS you control" }, { "name": "primitive.get_inbox_status", -"summary": "Get inbound inbox readiness" +"summary": "Get inbound inbox readiness", +"example": "{}", +"gated": null }, { "name": "primitive.list_emails", -"summary": "List inbound emails" +"summary": "List inbound emails", +"example": "{\"cursor\": \"\", \"limit\": 20, \"domain_id\": \"\", \"status\": \"\", \"search\": \"search terms\", \"date_from\": \"\", \"date_to\": \"\"}", +"gated": null }, { "name": "primitive.search_emails", -"summary": "Search inbound emails" +"summary": "Search inbound emails", +"example": "{\"q\": \"search terms\", \"from\": \"you@your-inbox.primitive.email\", \"to\": \"someone@example.com\", \"subject\": \"Subject line\", \"body\": \"\", \"domain_id\": \"\", \"reply_to_sent_email_id\": \"\"}", +"gated": null }, { "name": "primitive.get_email", -"summary": "Get inbound email by id" +"summary": "Get inbound email by id", +"example": "{\"id\": \"\"}", +"gated": null }, { "name": "primitive.delete_email", -"summary": "Delete an email" +"summary": "Delete an email", +"example": "{\"id\": \"\"}", +"gated": null }, { "name": "primitive.download_raw_email", -"summary": "Download raw email" +"summary": "Download raw email", +"example": "{\"id\": \"\", \"token\": \"\"}", +"gated": null }, { "name": "primitive.download_attachments", -"summary": "Download email attachments" +"summary": "Download email attachments", +"example": "{\"id\": \"\", \"token\": \"\"}", +"gated": null }, { "name": "primitive.reply_to_email", -"summary": "Reply to an inbound email" +"summary": "Reply to an inbound email", +"example": "{\"id\": \"\", \"body_text\": \"Plain-text body\", \"body_html\": \"

HTML body

\", \"from\": \"you@your-inbox.primitive.email\", \"wait\": 30, \"attachments\": [\"...\"]}", +"gated": null }, { "name": "primitive.replay_email_webhooks", -"summary": "Replay email webhooks" +"summary": "Replay email webhooks", +"example": "{\"id\": \"\"}", +"gated": null }, { "name": "primitive.discard_email_content", -"summary": "Discard email content" +"summary": "Discard email content", +"example": "{\"id\": \"\"}", +"gated": null }, { "name": "primitive.get_conversation", -"summary": "Get the conversation an email belongs to" +"summary": "Get the conversation an email belongs to", +"example": "{\"id\": \"\"}", +"gated": null }, { "name": "primitive.list_endpoints", -"summary": "List webhook endpoints" +"summary": "List webhook endpoints", +"example": "{}", +"gated": null }, { "name": "primitive.create_endpoint", -"summary": "Create a webhook endpoint" +"summary": "Create a webhook endpoint", +"example": "{\"kind\": \"http\", \"url\": \"https://example.com/webhook\", \"function_id\": \"\", \"enabled\": true, \"domain_id\": \"\", \"rules\": {\"...\": \"...\"}, \"is_route_target\": true}", +"gated": null }, { "name": "primitive.update_endpoint", -"summary": "Update a webhook endpoint" +"summary": "Update a webhook endpoint", +"example": "{\"id\": \"\", \"url\": \"https://example.com/webhook\", \"enabled\": true, \"domain_id\": \"\", \"rules\": {\"...\": \"...\"}}", +"gated": null }, { "name": "primitive.delete_endpoint", -"summary": "Delete a webhook endpoint" +"summary": "Delete a webhook endpoint", +"example": "{\"id\": \"\"}", +"gated": null }, { "name": "primitive.test_endpoint", -"summary": "Send a test webhook" +"summary": "Send a test webhook", +"example": "{\"id\": \"\"}", +"gated": null }, { "name": "primitive.list_filters", -"summary": "List filter rules" +"summary": "List filter rules", +"example": "{}", +"gated": null }, { "name": "primitive.create_filter", -"summary": "Create a filter rule" +"summary": "Create a filter rule", +"example": "{\"type\": \"whitelist\", \"pattern\": \"*@example.com\", \"domain_id\": \"\"}", +"gated": null }, { "name": "primitive.update_filter", -"summary": "Update a filter rule" +"summary": "Update a filter rule", +"example": "{\"id\": \"\", \"enabled\": true}", +"gated": null }, { "name": "primitive.delete_filter", -"summary": "Delete a filter rule" +"summary": "Delete a filter rule", +"example": "{\"id\": \"\"}", +"gated": null }, { "name": "primitive.list_wake_schedules", -"summary": "List wake schedules" +"summary": "List wake schedules", +"example": "{}", +"gated": "requires a plan/entitlement upgrade \u2014 Wake scheduling is not on the free agent plan" }, { "name": "primitive.create_wake_schedule", -"summary": "Create a wake schedule" +"summary": "Create a wake schedule", +"example": "{\"from_address\": \"\", \"target_address\": \"\", \"command\": \"\", \"cron_expr\": \"\", \"args\": {\"...\": \"...\"}, \"timezone\": \"\", \"note\": \"\"}", +"gated": "requires a plan/entitlement upgrade \u2014 Wake scheduling is not on the free agent plan" }, { "name": "primitive.get_wake_schedule", -"summary": "Get a wake schedule" +"summary": "Get a wake schedule", +"example": "{\"id\": \"\"}", +"gated": "requires a plan/entitlement upgrade \u2014 Wake scheduling is not on the free agent plan" }, { "name": "primitive.update_wake_schedule", -"summary": "Update a wake schedule" +"summary": "Update a wake schedule", +"example": "{\"id\": \"\", \"enabled\": true, \"command\": \"\", \"args\": {\"...\": \"...\"}, \"cron_expr\": \"\", \"timezone\": \"\", \"from_address\": \"\"}", +"gated": "requires a plan/entitlement upgrade \u2014 Wake scheduling is not on the free agent plan" }, { "name": "primitive.delete_wake_schedule", -"summary": "Delete a wake schedule" +"summary": "Delete a wake schedule", +"example": "{\"id\": \"\"}", +"gated": "requires a plan/entitlement upgrade \u2014 Wake scheduling is not on the free agent plan" }, { "name": "primitive.run_wake_schedule", -"summary": "Run a wake schedule now" +"summary": "Run a wake schedule now", +"example": "{\"id\": \"\"}", +"gated": "requires a plan/entitlement upgrade \u2014 Wake scheduling is not on the free agent plan" }, { "name": "primitive.list_wake_authorizations", -"summary": "List wake authorizations" +"summary": "List wake authorizations", +"example": "{\"recipient_endpoint_id\": \"\"}", +"gated": "requires a plan/entitlement upgrade \u2014 Wake scheduling is not on the free agent plan" }, { "name": "primitive.create_wake_authorization", -"summary": "Create a wake authorization" +"summary": "Create a wake authorization", +"example": "{\"recipient_endpoint_id\": \"\", \"allowed_sender_domain\": \"\", \"allowed_sender_address\": \"\", \"allowed_commands\": [\"...\"], \"note\": \"\"}", +"gated": "requires a plan/entitlement upgrade \u2014 Wake scheduling is not on the free agent plan" }, { "name": "primitive.update_wake_authorization", -"summary": "Update a wake authorization" +"summary": "Update a wake authorization", +"example": "{\"id\": \"\", \"enabled\": true}", +"gated": "requires a plan/entitlement upgrade \u2014 Wake scheduling is not on the free agent plan" }, { "name": "primitive.delete_wake_authorization", -"summary": "Delete a wake authorization" +"summary": "Delete a wake authorization", +"example": "{\"id\": \"\"}", +"gated": "requires a plan/entitlement upgrade \u2014 Wake scheduling is not on the free agent plan" }, { "name": "primitive.list_wake_dispatches", -"summary": "List recent wake dispatches" +"summary": "List recent wake dispatches", +"example": "{\"limit\": 20}", +"gated": "requires a plan/entitlement upgrade \u2014 Wake scheduling is not on the free agent plan" }, { "name": "primitive.list_routes", -"summary": "List recipient routes" +"summary": "List recipient routes", +"example": "{}", +"gated": "requires the recipient-routing feature \u2014 disabled on the free agent plan (the managed inbox routes to storage automatically)" }, { "name": "primitive.create_route", -"summary": "Create a recipient route" +"summary": "Create a recipient route", +"example": "{\"match_type\": \"to\", \"pattern\": \"*@example.com\", \"endpoint_id\": \"\", \"function_id\": \"\", \"domain_id\": \"\", \"priority\": 0, \"enabled\": true}", +"gated": "requires the recipient-routing feature \u2014 disabled on the free agent plan (the managed inbox routes to storage automatically)" }, { "name": "primitive.reorder_routes", -"summary": "Reorder recipient routes" +"summary": "Reorder recipient routes", +"example": "{\"updates\": [\"...\"]}", +"gated": "requires the recipient-routing feature \u2014 disabled on the free agent plan (the managed inbox routes to storage automatically)" }, { "name": "primitive.simulate_route", -"summary": "Simulate routing for a recipient" +"summary": "Simulate routing for a recipient", +"example": "{\"recipient\": \"someone@example.com\", \"event_type\": \"\"}", +"gated": "requires the recipient-routing feature \u2014 disabled on the free agent plan (the managed inbox routes to storage automatically)" }, { "name": "primitive.update_route", -"summary": "Update a recipient route" +"summary": "Update a recipient route", +"example": "{\"id\": \"\", \"match_type\": \"to\", \"pattern\": \"*@example.com\", \"endpoint_id\": \"\", \"domain_id\": \"\", \"priority\": 0, \"enabled\": true}", +"gated": "requires the recipient-routing feature \u2014 disabled on the free agent plan (the managed inbox routes to storage automatically)" }, { "name": "primitive.delete_route", -"summary": "Delete a recipient route" +"summary": "Delete a recipient route", +"example": "{\"id\": \"\"}", +"gated": "requires the recipient-routing feature \u2014 disabled on the free agent plan (the managed inbox routes to storage automatically)" }, { "name": "primitive.list_deliveries", -"summary": "List webhook deliveries" +"summary": "List webhook deliveries", +"example": "{\"cursor\": \"\", \"limit\": 20, \"email_id\": \"\", \"status\": \"\", \"date_from\": \"\", \"date_to\": \"\"}", +"gated": null }, { "name": "primitive.replay_delivery", -"summary": "Replay a webhook delivery" +"summary": "Replay a webhook delivery", +"example": "{\"id\": \"\"}", +"gated": null }, { "name": "primitive.get_send_permissions", -"summary": "List send-permission rules" +"summary": "List send-permission rules", +"example": "{}", +"gated": null }, { "name": "primitive.send_email", -"summary": "Send outbound email" +"summary": "Send outbound email", +"example": "{\"from\": \"you@your-inbox.primitive.email\", \"to\": \"someone@example.com\", \"subject\": \"Subject line\", \"body_text\": \"Plain-text body\", \"body_html\": \"

HTML body

\", \"in_reply_to\": \"\", \"references\": [\"...\"]}", +"gated": null }, { "name": "primitive.semantic_search", -"summary": "Semantic search across received and sent mail" +"summary": "Semantic search across received and sent mail", +"example": "{\"query\": \"search terms\", \"mode\": \"\", \"corpus\": [\"...\"], \"search_in\": [\"...\"], \"exclude\": [\"...\"], \"date_from\": \"\", \"date_to\": \"\"}", +"gated": "requires the Pro plan \u2014 semantic search over mail is not on the free agent plan" }, { "name": "primitive.list_sent_emails", -"summary": "List outbound sent emails" +"summary": "List outbound sent emails", +"example": "{\"cursor\": \"\", \"limit\": 20, \"status\": \"\", \"request_id\": \"\", \"idempotency_key\": \"\", \"date_from\": \"\", \"date_to\": \"\"}", +"gated": null }, { "name": "primitive.get_sent_email", -"summary": "Get a sent email by id" +"summary": "Get a sent email by id", +"example": "{\"id\": \"\"}", +"gated": null }, { "name": "primitive.get_thread", -"summary": "Get a conversation thread by id" +"summary": "Get a conversation thread by id", +"example": "{\"id\": \"\"}", +"gated": null }, { "name": "primitive.list_functions", -"summary": "List functions" +"summary": "List functions", +"example": "{}", +"gated": "requires the developer plan \u2014 confirm an email at primitive.dev to upgrade; hosted Functions are not on the free agent plan" }, { "name": "primitive.create_function", -"summary": "Deploy a function" +"summary": "Deploy a function", +"example": "{\"name\": \"\", \"code\": \"\", \"sourceMap\": \"\", \"files\": {\"...\": \"...\"}}", +"gated": "requires the developer plan \u2014 confirm an email at primitive.dev to upgrade; hosted Functions are not on the free agent plan" }, { "name": "primitive.get_function", -"summary": "Get a function" +"summary": "Get a function", +"example": "{\"id\": \"\"}", +"gated": "requires the developer plan \u2014 confirm an email at primitive.dev to upgrade; hosted Functions are not on the free agent plan" }, { "name": "primitive.update_function", -"summary": "Update and redeploy a function" +"summary": "Update and redeploy a function", +"example": "{\"id\": \"\", \"code\": \"\", \"sourceMap\": \"\", \"files\": {\"...\": \"...\"}}", +"gated": "requires the developer plan \u2014 confirm an email at primitive.dev to upgrade; hosted Functions are not on the free agent plan" }, { "name": "primitive.delete_function", -"summary": "Delete a function" +"summary": "Delete a function", +"example": "{\"id\": \"\"}", +"gated": "requires the developer plan \u2014 confirm an email at primitive.dev to upgrade; hosted Functions are not on the free agent plan" }, { "name": "primitive.test_function", -"summary": "Send a test invocation" +"summary": "Send a test invocation", +"example": "{\"id\": \"\", \"local_part\": \"\"}", +"gated": "requires the developer plan \u2014 confirm an email at primitive.dev to upgrade; hosted Functions are not on the free agent plan" }, { "name": "primitive.get_function_test_run_trace", -"summary": "Get a function test run trace" +"summary": "Get a function test run trace", +"example": "{\"id\": \"\", \"run_id\": \"\"}", +"gated": "requires the developer plan \u2014 confirm an email at primitive.dev to upgrade; hosted Functions are not on the free agent plan" }, { "name": "primitive.get_org_routing_topology", -"summary": "Get the org's function routing topology" +"summary": "Get the org's function routing topology", +"example": "{}", +"gated": "requires the developer plan \u2014 confirm an email at primitive.dev to upgrade; hosted Functions are not on the free agent plan" }, { "name": "primitive.get_function_routing", -"summary": "Get a function's current route binding" +"summary": "Get a function's current route binding", +"example": "{\"id\": \"\"}", +"gated": "requires the developer plan \u2014 confirm an email at primitive.dev to upgrade; hosted Functions are not on the free agent plan" }, { "name": "primitive.set_function_route", -"summary": "Bind a route to a function" +"summary": "Bind a route to a function", +"example": "{\"id\": \"\", \"target\": {\"...\": \"...\"}, \"takeover\": true}", +"gated": "requires the developer plan \u2014 confirm an email at primitive.dev to upgrade; hosted Functions are not on the free agent plan" }, { "name": "primitive.unset_function_route", -"summary": "Unbind any route from a function" +"summary": "Unbind any route from a function", +"example": "{\"id\": \"\"}", +"gated": "requires the developer plan \u2014 confirm an email at primitive.dev to upgrade; hosted Functions are not on the free agent plan" }, { "name": "primitive.list_function_secrets", -"summary": "List a function's secrets" +"summary": "List a function's secrets", +"example": "{\"id\": \"\"}", +"gated": "requires the developer plan \u2014 confirm an email at primitive.dev to upgrade; hosted Functions are not on the free agent plan" }, { "name": "primitive.create_function_secret", -"summary": "Create or update a secret" +"summary": "Create or update a secret", +"example": "{\"id\": \"\", \"key\": \"namespace/key\", \"value\": {\"any\": \"json\"}}", +"gated": "requires the developer plan \u2014 confirm an email at primitive.dev to upgrade; hosted Functions are not on the free agent plan" }, { "name": "primitive.set_function_secret", -"summary": "Set a secret by key" +"summary": "Set a secret by key", +"example": "{\"id\": \"\", \"key\": \"namespace/key\", \"value\": {\"any\": \"json\"}}", +"gated": "requires the developer plan \u2014 confirm an email at primitive.dev to upgrade; hosted Functions are not on the free agent plan" }, { "name": "primitive.delete_function_secret", -"summary": "Delete a secret" +"summary": "Delete a secret", +"example": "{\"id\": \"\", \"key\": \"namespace/key\"}", +"gated": "requires the developer plan \u2014 confirm an email at primitive.dev to upgrade; hosted Functions are not on the free agent plan" }, { "name": "primitive.list_org_secrets", -"summary": "List org-level (global) secrets" +"summary": "List org-level (global) secrets", +"example": "{}", +"gated": "requires the developer plan \u2014 confirm an email at primitive.dev to upgrade; hosted Functions are not on the free agent plan" }, { "name": "primitive.create_org_secret", -"summary": "Create or update an org secret" +"summary": "Create or update an org secret", +"example": "{\"key\": \"namespace/key\", \"value\": {\"any\": \"json\"}}", +"gated": "requires the developer plan \u2014 confirm an email at primitive.dev to upgrade; hosted Functions are not on the free agent plan" }, { "name": "primitive.set_org_secret", -"summary": "Set an org secret by key" +"summary": "Set an org secret by key", +"example": "{\"key\": \"namespace/key\", \"value\": {\"any\": \"json\"}}", +"gated": "requires the developer plan \u2014 confirm an email at primitive.dev to upgrade; hosted Functions are not on the free agent plan" }, { "name": "primitive.delete_org_secret", -"summary": "Delete an org secret" +"summary": "Delete an org secret", +"example": "{\"key\": \"namespace/key\"}", +"gated": "requires the developer plan \u2014 confirm an email at primitive.dev to upgrade; hosted Functions are not on the free agent plan" }, { "name": "primitive.list_function_logs", -"summary": "List a function's execution logs" +"summary": "List a function's execution logs", +"example": "{\"id\": \"\", \"limit\": 20, \"cursor\": \"\"}", +"gated": "requires the developer plan \u2014 confirm an email at primitive.dev to upgrade; hosted Functions are not on the free agent plan" }, { "name": "primitive.set_memory", -"summary": "Set a memory" +"summary": "Set a memory", +"example": "{\"key\": \"namespace/key\", \"value\": {\"any\": \"json\"}, \"scope\": {\"...\": \"...\"}, \"ttl_seconds\": 10, \"expires_at\": \"\", \"clear_ttl\": true, \"if_absent\": true}", +"gated": null }, { "name": "primitive.get_memory", -"summary": "Get a memory" +"summary": "Get a memory", +"example": "{\"key\": \"namespace/key\", \"scope_type\": \"\", \"scope_id\": \"\"}", +"gated": null }, { "name": "primitive.delete_memory", -"summary": "Delete a memory" +"summary": "Delete a memory", +"example": "{\"key\": \"namespace/key\", \"scope_type\": \"\", \"scope_id\": \"\", \"if_version\": \"\"}", +"gated": null }, { "name": "primitive.search_memories", -"summary": "Search memories" +"summary": "Search memories", +"example": "{\"prefix\": \"search terms\", \"cursor\": \"\", \"limit\": 20, \"include_value\": \"\", \"updated_after\": \"\", \"updated_before\": \"\", \"scope_type\": \"\"}", +"gated": null }, { "name": "primitive.register_payout_address", -"summary": "Register a payout address" +"summary": "Register a payout address", +"example": "{\"address\": \"someone@example.com\", \"network\": \"\", \"signature\": \"\", \"issued_at\": \"\", \"label\": \"