diff --git a/README.md b/README.md index 67b7d248ae..a73805f486 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ Bankr Skills equip builders with plug-and-play tools to build more powerful agen | [Bankr](https://bankr.bot) | [bankr](bankr/) | Launch a token, earn from every trade, and fund your agent. Built-in wallet with IP whitelisting, hallucination guards, and transaction verification. | | [Bankr](https://bankr.bot) | [bankr-token-scam-analysis](bankr-token-scam-analysis/) | Forensic on-chain scam and rug-pull analysis for EVM tokens. Produces a risk verdict backed by on-chain facts. | | [Bankr](https://bankr.bot) | [bankr-twitter-agent](bankr-twitter-agent/) | Framework for creating, managing, and automating a Twitter/X agent with a persistent personality and voice. | +| [Bankr Space](https://bankr.space) | [bankr-communities](bankr-communities/) | Token-gated holder spaces on bankr.space — links, briefing, posts, verify, pin, X reply "post this" routing. v1.7.1 | | [BuiltByEcho](https://www.builtbyecho.xyz) | [agent-wormhole](agent-wormhole/) | One-time sealed handoffs for autonomous agents. Send encrypted mission briefs, scoped secrets, artifacts, and config drops with ECHO holder access or Bankr x402 paid opens. | | [DARKSOL](https://darksol.net) | [darksol-random-oracle](darksol-random-oracle/) | On-chain verifiable randomness on Base. Generate random numbers, coin flips, dice rolls, sequences, and shuffles with x402 USDC payments or free DARKSOL holder access. | | [Builder's Garden](https://builders.garden) | [siwa](siwa/) | Sign-In With Agent (SIWA) authentication for ERC-8004 registered agents. Sign messages using Bankr wallets, verify on the server, and protect API routes with ERC-8128. | diff --git a/bankr-communities/BENEFICIARY-ACTIONS.md b/bankr-communities/BENEFICIARY-ACTIONS.md new file mode 100644 index 0000000000..93cf5cde66 --- /dev/null +++ b/bankr-communities/BENEFICIARY-ACTIONS.md @@ -0,0 +1,180 @@ +# Beneficiary actions — verify, profile, pin (tweet + terminal) + +> Same pipeline as **post in space**. User does NOT need to say `use_skill`. Load `bankr-communities` → call API → plain English reply + space URL. + +**Site:** `https://bankr.space` +**Writes:** header `x-wallet-address: {user's linked Bankr wallet}` — never the thread starter's wallet. + +--- + +## Who can do what + +| Action | Who | Space must be verified? | +|--------|-----|----------------------------| +| **Verify** | Fee beneficiary only | No (this creates verified) | +| **Update profile / social links** | Fee beneficiary only | No | +| **Post / comment** | Holder OR beneficiary OR deployer | No | +| **Pin / unpin post** | Fee beneficiary only | **Yes** | + +Check before writes: + +```http +GET /api/holders/{tokenAddress}?wallet={linked} +``` + +Use: `canEditProfile`, `canPinPosts`, `canPost`, `isBeneficiary`. + +--- + +## Verify space + +**User says:** +```text +@bankrbot verify the TMP space +@bankrbot verify space for $TMP +``` + +**Steps:** +``` +1. GET /api/agent/briefing?symbol=TMP → get tokenAddress, community.verified +2. If already verified → "TMP space is already verified" + communityLink → STOP +3. POST /api/communities/{tokenAddress}/verify + Header: x-wallet-address: {linked} +4. Reply: "Verified $TMP space ✓" + communityLink on its own line → STOP +5. 403 → "Only the token fee beneficiary can verify" + communityLink +``` + +--- + +## Update profile / add social links + +**User says:** +```text +@bankrbot add website https://tokenmarketplace.shop to TMP space +@bankrbot update TMP space profile: website tokenmarketplace.shop telegram t.me/tmp +@bankrbot set TMP space description: Token marketplace for holders +@bankrbot add these links to TMP token info: x @MyToken github myorg/repo +``` + +**Editable fields:** `description`, `socialLinks.x`, `socialLinks.website`, `socialLinks.github`, `socialLinks.telegram`, `socialLinks.discord` + +**NOT editable via API:** beneficiary wallet (from Bankr launch data). + +**Steps:** +``` +1. GET /api/holders/{token}?wallet={linked} → if !canEditProfile → 403 message → STOP +2. GET /api/communities/{tokenAddress} → read current description + socialLinks +3. Merge user-requested fields into body (keep existing fields not mentioned) +4. PATCH /api/communities/{tokenAddress} + Body: { "description": "...", "socialLinks": { "website": "...", "x": "...", ... } } + Header: x-wallet-address: {linked} +5. Reply: "Updated $TMP space profile" + list what changed + communityLink → STOP +``` + +**PATCH body example:** +```json +{ + "description": "Token Market Place for holders.", + "socialLinks": { + "website": "https://tokenmarketplace.shop", + "x": "https://x.com/MyToken", + "telegram": "https://t.me/mytoken", + "discord": "https://discord.gg/mytoken" + } +} +``` + +--- + +## Pin a post + +**User says:** +```text +@bankrbot pin post post_123 in TMP space +@bankrbot unpin post post_123 in TMP space +@bankrbot pin the latest post in TMP space +``` + +**Steps:** +``` +1. GET /api/holders/{token}?wallet={linked} → if !canPinPosts → "Verify space first / beneficiary only" → STOP +2. Resolve postId (from message, or GET /api/communities/{token} → latest post id) +3. POST /api/communities/{tokenAddress}/pin-post + Body: { "postId": "post_123", "action": "pin" | "unpin" } + Header: x-wallet-address: {linked} +4. Reply: "Pinned post in $TMP space" (most recent pin shows first) + communityLink → STOP +``` + +--- + +## Post AND pin (combined) + +**Before building `content`:** read **`X-REPLY-POST-CONTENT.md`** — X reply “post this” → parent tweet URL; explicit text → user’s words only. + +**User says:** +```text +@bankrbot post in TMP space: launch update — and pin it +@bankrbot post in TMP space: gm holders then pin +``` + +**Steps:** +``` +1. GET /api/holders/{token}?wallet={linked} → if !canPost → explain holder/owner required → STOP +2. POST /api/communities/{tokenAddress}/posts + body: { + "content": "...", + "source": { + "client": "agent", + "trigger": "x-dm | x-mention | x-reply | terminal", + "viaAgent": true, + "agentId": "bankrbot", + "externalRef": "{id_if_known}" + } + } + headers: x-wallet-address, x-client: agent + → save postId from response + See POST-SOURCE.md for trigger selection. +3. If user asked to pin: + - GET /api/holders/{token}?wallet={linked} again → if canPinPosts: + POST /api/communities/{tokenAddress}/pin-post body: { "postId": "{postId}", "action": "pin" } + - else: confirm post but say "Only verified beneficiary can pin — post is live unpinned" +4. Reply: paste post replyText from step 2 + "pinned ✓" if step 3 ran → STOP +``` + +--- + +## Tweet examples (copy-paste tests) + +```text +@bankrbot verify the TMP space +@bankrbot add website https://tokenmarketplace.shop to TMP space profile +@bankrbot post in TMP space: big update for holders — pin it +@bankrbot pin the latest post in TMP space +@bankrbot post in ARCHIVE space: gm +``` + +--- + +## Reply format (every write) + +```text +posted to $TMP holder space: "launch update" +pinned ✓ + +https://bankr.space/community/0x935e13a28849095db45e63040f109c34b757aba3 +``` + +Always include **communityLink** on its own line. Never `bankr.bot`. + +--- + +## Routing (Bankr platform) + +These phrases MUST load `bankr-communities` **before** tool selection — same as `post in space`: + +- verify space / verify $TICKER +- update profile / add links / add website / set description + space/community or token +- pin post / pin it / unpin + space/community +- post in space + pin + +**Fail:** generic "I wasn't able to generate a response" without calling API. diff --git a/bankr-communities/GET-LINK.md b/bankr-communities/GET-LINK.md new file mode 100644 index 0000000000..ffdc9df278 --- /dev/null +++ b/bankr-communities/GET-LINK.md @@ -0,0 +1,67 @@ +# GET link — run exactly like terminal curl + +> **Highest priority.** User asks for a space **link** (may say community), **URL**, or **where is** $TICKER space (or community). + +## Do this (3 steps) + +``` +1. Extract ticker from user message (strip $ and "community" words) + Example: "what's the link to the TMP space?" → TMP + +2. HTTP GET (same as terminal curl): + https://bankr.space/api/agent/link?q=TMP + + Bankr terminal equivalent: + curl "https://bankr.space/api/agent/link?q=TMP" + + Bankr script equivalent: + const body = await http.fetch('https://bankr.space/api/agent/link?q=TMP'); + +3. Tweet reply = response body verbatim. One line. Do not add text before or after. +``` + +**The API returns plain text — not JSON.** The entire response body is what you paste in the tweet. + +--- + +## Examples + +| User says | GET URL | Tweet reply (response body) | +|-----------|---------|----------------------------| +| link to **TMP** space | `.../api/agent/link?q=TMP` | `https://bankr.space/community/0x935e13a28849095db45e63040f109c34b757aba3` | +| link to **ARCHIVE** | `.../api/agent/link?q=ARCHIVE` | `https://bankr.space/community/0x76aba8089e4ba07f705fb886d17dd41793ad2ba3` | +| token exists, no space yet | `.../api/agent/link?q=FOO` | `No $FOO space yet — TokenName is on Bankr. Would you like me to create the space?` | + +Replace `TMP` with whatever ticker/name/address the user asked for. + +--- + +## If HTTP GET fails — use fallback (never fail silently) + +Read `known-communities.json`. Never reply "I wasn't able to generate a response." + +| Symbol | communityLink | +|--------|---------------| +| TMP | `https://bankr.space/community/0x935e13a28849095db45e63040f109c34b757aba3` | +| ARCHIVE | `https://bankr.space/community/0x76aba8089e4ba07f705fb886d17dd41793ad2ba3` | + +--- + +## JSON alternative (if you need fields) + +```http +GET https://bankr.space/api/agent/resolve-community?q=TMP +``` + +Use field `communityLink` or `tweetReply` from JSON. + +Plain text is preferred: `GET .../api/agent/link?q=TMP` + +--- + +## FORBIDDEN + +- `bankr.bot`, `t.co`, `/community/TMP` (symbol in path) +- Empty reply or "I wasn't able to generate a response" +- FAQ when user only asked for a link +- Inventing URLs without GET or known-communities fallback diff --git a/bankr-communities/INSTANT-LINK-REPLIES.md b/bankr-communities/INSTANT-LINK-REPLIES.md new file mode 100644 index 0000000000..1a35b288dd --- /dev/null +++ b/bankr-communities/INSTANT-LINK-REPLIES.md @@ -0,0 +1,33 @@ +# Instant link replies — NO HTTP, NO TOOLS + +> **Tweet intake often cannot run http.fetch.** For known tokens, reply from this table **immediately**. Do not call tools first. Never reply "I wasn't able to generate a response." + +## Match user message → paste this line only + +| If message mentions | Reply (exactly one line) | +|---------------------|--------------------------| +| **TMP** + link / url / space | `https://bankr.space/community/0x935e13a28849095db45e63040f109c34b757aba3` | +| **ARCHIVE** + link / url / space | `https://bankr.space/community/0x76aba8089e4ba07f705fb886d17dd41793ad2ba3` | +| **PMFI** + link / url / space | `https://bankr.space/community/0xd77ce6d3137342bb5174673bdab5f51db16fcba3` | + +Examples that match TMP row: +- "what's the link to the TMP space?" +- "TMP community url" +- "where is $TMP space" + +## Other tickers (HTTP only if instant table miss) + +```http +GET https://bankr.space/api/agent/link?q=PEPE +``` + +Paste response body. If HTTP fails → say token not found or ask to create — **never** empty error. + +## Why two paths + +| Context | What works | +|---------|------------| +| Bankr **terminal** | `http.fetch` / curl → API works | +| Bankr **tweet** | Skill may not run HTTP → use **instant table** above for TMP/ARCHIVE | + +**Terminal and tweet must give the same URL for TMP.** diff --git a/bankr-communities/LINK-INTENT-ONLY.md b/bankr-communities/LINK-INTENT-ONLY.md new file mode 100644 index 0000000000..10a47c2347 --- /dev/null +++ b/bankr-communities/LINK-INTENT-ONLY.md @@ -0,0 +1,11 @@ +# Link questions — read INSTANT-LINK-REPLIES.md first + +> **Tweet intake:** paste URL from skill table — **no HTTP required** for TMP/ARCHIVE. + +**TMP:** `https://bankr.space/community/0x935e13a28849095db45e63040f109c34b757aba3` + +**ARCHIVE:** `https://bankr.space/community/0x76aba8089e4ba07f705fb886d17dd41793ad2ba3` + +Other tickers → `GET-LINK.md` (curl / http.fetch). + +Never reply "I wasn't able to generate a response." diff --git a/bankr-communities/NOT-TWITTER-X-SPACES.md b/bankr-communities/NOT-TWITTER-X-SPACES.md new file mode 100644 index 0000000000..fe057cd716 --- /dev/null +++ b/bankr-communities/NOT-TWITTER-X-SPACES.md @@ -0,0 +1,63 @@ +# NOT Twitter/X audio Spaces — Bankr Space only + +**Read this when user says "post in $TICKER space" on X.** + +--- + +## What "space" means here + +| User says | Means | You do | +|-----------|-------|--------| +| post in **$PMFI space** | **Bankr Space** on `bankr.space` — token-gated holder feed | `use_skill("bankr-communities")` → `POST …/api/communities/{token}/posts` | +| post **this** in $TICKER space (X reply) | Same — content = parent tweet URL | **X-REPLY-POST-CONTENT.md** Mode A | +| "X Spaces" / "Twitter Spaces" / audio room | **Different product** — not this skill | Only if user explicitly asks about Twitter audio | + +**Bankr Space ≠ Twitter/X audio Spaces.** Users say "space" for **bankr.space/community/0x…** — never refuse as "can't post to X spaces." + +--- + +## Forbidden replies (never say these) + +When user mentions `$TICKER space`, `post in … space`, `post this in … space`, or `community`: + +- ❌ "I don't have the ability to post to **X spaces** or communities directly" +- ❌ "I can only reply within this thread" +- ❌ "You'll need to post it manually from your account" +- ❌ "I can't access communities" +- ❌ Confusing **bankr.space** with **Twitter Spaces** (audio) + +**Correct:** load skill → resolve ticker (`GET /api/agent/link?q=PMFI`) → holder check → post via API → reply with confirmation + `https://bankr.space/community/0x…` + +--- + +## Example (production failure → correct behavior) + +**User** (replying to a tweet): + +```text +@bankrbot post this in $pmfi space +``` + +**Wrong:** refuse as Twitter/X Spaces limitation. + +**Right:** + +1. `use_skill("bankr-communities")` +2. Resolve PMFI → `0xd77ce6d3137342bb5174673bdab5f51db16fcba3` +3. Parent tweet URL → `content` (Mode A — **X-REPLY-POST-CONTENT.md**) +4. `POST https://bankr.space/api/communities/0xd77ce6d3137342bb5174673bdab5f51db16fcba3/posts` with `source.trigger: x-reply` +5. Reply: + +```text +Posted to $PMFI holder space. + +https://bankr.space/community/0xd77ce6d3137342bb5174673bdab5f51db16fcba3 +``` + +--- + +## Trigger phrases (always → this skill) + +`post in`, `post this`, `share this`, `put that`, `comment in`, `verify`, `pin`, `latest on`, `members in`, `link to`, `space for`, `community for` + ticker or `0x…` address. + +See **BANKR-PLATFORM-TWEET-INTAKE.md**, **ONE-LINE-INTENTS.md**, **AGENT-ROUTING-COMMUNITIES.md**. diff --git a/bankr-communities/ONE-LINE-INTENTS.md b/bankr-communities/ONE-LINE-INTENTS.md new file mode 100644 index 0000000000..16a4029e34 --- /dev/null +++ b/bankr-communities/ONE-LINE-INTENTS.md @@ -0,0 +1,81 @@ +# One-line intents — Bankr Space + +> User gives **one sentence** → agent runs **full flow** without interview. + +**Site base:** `https://bankr.space` (or `{COMMUNITIES_SITE_URL}` env override) + +--- + +## Read-only (no wallet tx) + +| User says | API | Reply | +|-----------|-----|-------| +| what's the link to **$TMP** space? | `GET /api/agent/link?q=TMP` → paste response body (plain text URL) | +| search live spaces **archive** | `GET /api/agent/search-communities?q=archive` | +| what's the latest on **$TMP** space? | briefing → paste **`replyText` verbatim** (URL on **last** line) | +| how many **members** in **CTO** space? | `GET /api/agent/briefing?symbol=CTO` → `stats.memberCount` | "N members in $CTO space" | +| show **recent posts** for **0x935e…** | `GET /api/communities/0x935e…` | summarize last 5 posts | +| **list** all spaces | `GET /api/communities` | count + top symbols | +| search Bankr token **PEPE** | `GET /api/tokens/search?q=PEPE` | launches found | +| is there a space for **$TMP**? | `GET /api/agent/briefing?symbol=TMP` | yes/no + link | +| what **opportunities** on spaces? | briefing → `opportunities[]` | unverified, first post, create space | + +--- + +## Write (linked wallet + API) + +| User says | Flow | +|-----------|------| +| **start** / **create** space for **$TMP** | search → `POST /api/communities/{token}` `{ description? }` + header `x-wallet-address: {linked}` | +| **verify** **$TMP** space | `GET /api/holders/{token}?wallet={linked}` → `POST /api/communities/{token}/verify` (fee beneficiary) | +| **update** / **add links** to **$TMP** profile | `GET /api/communities/{token}` → merge → `PATCH /api/communities/{token}` `{ description, socialLinks }` (beneficiary) | +| **pin** post in **TMP** / **pin it** after post | `POST /api/communities/{token}/pin-post` `{ postId, action: "pin" }` (verified beneficiary) | +| **post** in **TMP** space: {text} **and pin** | post → then pin-post if `canPinPosts` | +| **post** in **TMP** space: {text} | holder check → **X-REPLY-POST-CONTENT.md** → `POST …/posts` **with `source`** | +| **post this** in **$BNKR** space (X reply to a tweet) | **X-REPLY-POST-CONTENT.md** → parent status URL as `content` | +| **post** {inline text} in **$xxx** space (no colon) | **X-REPLY-POST-CONTENT.md** → inline text only, not parent tweet | +| **comment** in **0x935e…** space: {text} | same as post | +| react **👍** on post **{id}** in **TMP** | `POST /api/posts/{id}/react` `{ tokenAddress, reaction: "👍" }` | + +--- + +## Tweet examples (sufficient — no "use skill") + +```text +@bankrbot what's the latest on the TMP space? +@bankrbot what's the latest on the TMP community? ← same intent +@bankrbot verify the TMP space +@bankrbot add website https://tokenmarketplace.shop to TMP space profile +@bankrbot post in TMP space: launch update — pin it +@bankrbot pin the latest post in TMP space +@bankrbot post in TMP space: gm holders +@bankrbot post this in BNKR space +@bankrbot post xxxxx ewrwe xx test test in $xxx space +@bankrbot start a space for 0x935e13a28849095db45e63040f109c34b757aba3 +``` + +--- + +## Forbidden + +- Reply without calling site API first +- Ask "which skill?" or "paste use_skill" +- Ask wallet if user is X↔Bankr linked +- Say "open the website" when API write is available +- Fabricate member counts or posts + +--- + +## Combined with TMP + +| Domain | Skill | +|--------|-------| +| List / buy / claim fees / launch | `bankr-tmp-skill` | +| Space posts / verify / members | `bankr-communities` (this) | + +Example thread: + +```text +@bankrbot claim fees for CTO → TMP skill +@bankrbot what's new in CTO space → Bankr Space skill +``` diff --git a/bankr-communities/POST-SOURCE.md b/bankr-communities/POST-SOURCE.md new file mode 100644 index 0000000000..3af8b3a8d3 --- /dev/null +++ b/bankr-communities/POST-SOURCE.md @@ -0,0 +1,153 @@ +# Post source — mandatory for agent writes + +Every **`POST /api/communities/{token}/posts`** from Bankr (tweet, DM, or terminal) **must** include `source` so the space feed shows how the post was submitted (e.g. **Posted via @bankrbot · X DM**). + +--- + +## Required headers + +```http +x-wallet-address: {linked_bankr_wallet} +x-client: agent +Content-Type: application/json +``` + +Optional headers (also accepted instead of body fields): + +```http +x-post-trigger: x-dm +x-agent-id: bankrbot +x-external-ref: {tweet_or_dm_id} +``` + +--- + +## Required body shape + +```json +{ + "content": "Hello holders", + "source": { + "client": "agent", + "trigger": "x-dm", + "viaAgent": true, + "agentId": "bankrbot", + "externalRef": "1234567890123456789" + } +} +``` + +| Field | Rule | +|-------|------| +| `source.client` | Always `"agent"` for @bankrbot | +| `source.viaAgent` | Always `true` | +| `source.agentId` | Always `"bankrbot"` (or platform agent slug) | +| `source.trigger` | See table below — **never omit** | +| `source.externalRef` | Tweet id, DM id, or conversation id when Bankr provides it | + +--- + +## Pick `trigger` from intake channel + +| User reached Bankr via | `source.trigger` | +|------------------------|------------------| +| X **DM** / private message | `x-dm` | +| Public **@mention** of @bankrbot | `x-mention` | +| **Reply** in a tweet thread | `x-reply` | +| Bankr **terminal** / CLI | `terminal` | +| Autopilot / cron / no user message context | `autopilot` | +| Unclear but definitely agent | `autopilot` | + +**What goes in `content` for X replies:** read **`X-REPLY-POST-CONTENT.md`** (parent tweet URL vs explicit user text). + +**Default for tweet/DM pipeline:** if DM context → `x-dm`; if public tweet reply with parent → `x-reply`; if top-level mention → `x-mention`. + +--- + +## Full example (X DM) + +```http +POST https://bankr.space/api/communities/0x935e13a28849095db45e63040f109c34b757aba3/posts +x-wallet-address: 0x374d…13b4 +x-client: agent + +{ + "content": "Launch update for holders", + "source": { + "client": "agent", + "trigger": "x-dm", + "viaAgent": true, + "agentId": "bankrbot", + "externalRef": "1998765432109876543" + } +} +``` + +--- + +## Full example (public tweet) + +```http +POST …/posts +x-wallet-address: {linked} +x-client: agent + +{ + "content": "gm holders", + "source": { + "client": "agent", + "trigger": "x-mention", + "viaAgent": true, + "agentId": "bankrbot", + "externalRef": "1998765432109876544" + } +} +``` + +--- + +## Full example (Bankr terminal) + +```json +{ + "content": "hello from terminal", + "source": { + "client": "agent", + "trigger": "terminal", + "viaAgent": true, + "agentId": "bankrbot" + } +} +``` + +--- + +## Checklist before every post write + +1. `GET /api/holders/{token}?wallet={linked}` → `canPost` +2. Build `content` (max 2000 chars) +3. Set `source` using table above — **do not skip** +4. `POST …/posts` with headers + body +5. Reply with `replyText` + space URL + +--- + +## UI labels users see + +| trigger | Label | +|---------|--------| +| `x-dm` | Posted via @bankrbot · X DM | +| `x-mention` | Posted via @bankrbot · X mention | +| `x-reply` | Posted via @bankrbot · X reply | +| `terminal` | Posted via @bankrbot · terminal | +| `autopilot` | Posted via @bankrbot | + +--- + +## Fail rules + +- **Never** post without `source` when acting as @bankrbot +- **Never** omit `trigger` — pick best match from intake +- Include `externalRef` whenever Bankr exposes tweet/DM id + +See also: `references/community-api-reference.md`, `{SITE}/agent.md` diff --git a/bankr-communities/SKILL.md b/bankr-communities/SKILL.md new file mode 100644 index 0000000000..5e6c562f6c --- /dev/null +++ b/bankr-communities/SKILL.md @@ -0,0 +1,241 @@ +--- +name: bankr-communities +version: 1.7.1 +description: >- + Bankr Space on bankr.space — NOT Twitter audio Spaces. Post/verify/pin via API. X reply post THIS = parent tweet URL. Read NOT-TWITTER-X-SPACES.md + X-REPLY-POST-CONTENT.md. PMFI: https://bankr.space/community/0xd77ce6d3137342bb5174673bdab5f51db16fcba3 +siteUrl: https://bankr.space +communitiesSiteUrl: https://bankr.space +COMMUNITIES_SITE_URL: https://bankr.space +communityUrlTemplate: https://bankr.space/community/{tokenContractAddress} +linkApiTemplate: https://bankr.space/api/agent/link?q={TICKER} +metadata: + siteEnvVar: COMMUNITIES_SITE_URL + defaultSiteUrl: https://bankr.space + forbiddenLinkDomains: bankr.bot,t.co + primaryLinkEndpoint: https://bankr.space/api/agent/link?q={TICKER} + tmpCommunityLink: https://bankr.space/community/0x935e13a28849095db45e63040f109c34b757aba3 + archiveCommunityLink: https://bankr.space/community/0x76aba8089e4ba07f705fb886d17dd41793ad2ba3 +--- + +# Bankr Space — Agent skill + +Read **`NOT-TWITTER-X-SPACES.md`** first: **"post in $PMFI space"** = **bankr.space** API — **not** Twitter/X audio Spaces. Never refuse as "can't post to X spaces." + +Read **`TERMINOLOGY.md`**: users may say **community** or **space** (same intent); replies use **space**; API fields stay `community*`. + +## ⚡ WRITE ACTIONS — verify, post, pin, profile (same as post-in-space) + +User says **verify**, **post**, **pin**, **add links**, **update profile** → read **`BENEFICIARY-ACTIONS.md`** → for **post** also read **`X-REPLY-POST-CONTENT.md`** (X reply vs explicit text) and **`POST-SOURCE.md`** → use linked wallet → call API → reply + space URL. + +| User says | Agent does | +|-----------|------------| +| **verify** the **TMP** space (or community) | `POST …/verify` (fee beneficiary wallet) | +| **add website** / **update profile** for **TMP** | `PATCH …/communities/{token}` `{ socialLinks, description }` | +| **post** in **TMP**: text **and pin it** | `POST …/posts` **with `source`** → `POST …/pin-post` if verified beneficiary | +| **pin** latest post in **TMP** | `POST …/pin-post` `{ postId, action: "pin" }` | + +**Post writes:** always send `source` (`client: agent`, `trigger: x-dm` | `x-mention` | `x-reply` | `terminal`, `viaAgent: true`, `agentId: bankrbot`). See **`POST-SOURCE.md`**. + +Check permissions: `GET /api/holders/{token}?wallet={linked}` → `canEditProfile`, `canPinPosts`, `canPost`. + +--- + +## ⚡ LINK QUESTIONS — instant reply (no tools needed) + +User asks **"what's the link to the TMP space?"** → read **`INSTANT-LINK-REPLIES.md`** → paste URL from table. **Do not call HTTP first.** **Never** reply empty. + +| Token | Tweet reply (one line only) | +|-------|----------------------------| +| **TMP** | `https://bankr.space/community/0x935e13a28849095db45e63040f109c34b757aba3` | +| **ARCHIVE** | `https://bankr.space/community/0x76aba8089e4ba07f705fb886d17dd41793ad2ba3` | + +For **other** tickers → `GET https://bankr.space/api/agent/link?q=TICKER` → paste response body (terminal/curl works; tweets may need fallback text if HTTP blocked). + +```bash +curl "https://bankr.space/api/agent/link?q=TMP" +``` + +**Search live communities:** + +```http +GET https://bankr.space/api/agent/search-communities?q=archive +``` + +**JSON alternative:** `GET /api/agent/resolve-community?q=TMP` → use `communityLink` or `tweetReply`. + +--- +## LINK RULES (mandatory for every space reply) + +```text +https://bankr.space/community/{tokenContractAddress} +``` + +| Token | Link | +|-------|------| +| $TMP | `https://bankr.space/community/0x935e13a28849095db45e63040f109c34b757aba3` | +| $ARCHIVE | `https://bankr.space/community/0x76aba8089e4ba07f705fb886d17dd41793ad2ba3` | + +**FORBIDDEN:** `bankr.bot`, `t.co`, `/community/TMP`, `/community/ARCHIVE`, or any URL not on `bankr.space/community/0x…` + +**Link questions** ("what's the link", "space URL"): +1. `GET https://bankr.space/api/agent/link?q=ARCHIVE` +2. Tweet reply = **response body only** — one line, full https URL + +**Never invent links. Never substitute bankr.bot.** Read `references/COMMUNITY-LINK-RULES.md`. + +All `{SITE}` references below = `https://bankr.space`. + +**Install:** + +```text +install Bankr Space skill at https://github.com/anondevv69/bankr-community/tree/main/skills/bankr-communities +``` + +**Site API base:** `https://bankr.space` (override via `COMMUNITIES_SITE_URL` env if needed). +**Public agent guide:** `https://bankr.space/agent.md` +**Public reads** need no wallet. **Writes** use the user's **linked Bankr wallet** in header `x-wallet-address`. + +--- + +## TRIGGER → action (no skill jargon required) + +Users say natural language on **tweet** or **terminal**. Bankr must **`use_skill("bankr-communities")`** **before** generic tools. + +| User says | Agent does | +|-----------|------------| +| what's the link to **$TMP** space? | Paste TMP URL from table above — **no HTTP** | +| what's the link to **$ARCHIVE**? | Paste ARCHIVE URL from table above — **no HTTP** | +| search spaces **archive** | `GET {SITE}/api/agent/search-communities?q=archive` | +| what's the latest on **$TMP** space? | `GET {SITE}/api/agent/briefing?symbol=TMP` → paste **`replyText` verbatim** (URL is **last line**) — or `?format=text` | +| how many members in **TMP** space? | briefing → `stats.memberCount` | +| show recent posts in **0x935e…** space | `GET {SITE}/api/communities/0x935e…` | +| **verify** the **TMP** space (or community) | `BENEFICIARY-ACTIONS.md` → `POST …/verify` | +| **add links** / **update profile** for **TMP** | `PATCH …/communities/{token}` (beneficiary) | +| **post** in **TMP** space: hello **and pin it** | post → pin-post if `canPinPosts` | +| **pin** post in **TMP** space | `POST …/pin-post` | +| **post** in **TMP** space: hello holders | holder check → **`X-REPLY-POST-CONTENT.md`** (explicit text) → `POST …/posts` **with `source`** | +| **post this** in **$BNKR** space (X reply to a tweet) | **`X-REPLY-POST-CONTENT.md`** (parent tweet URL) → `POST …/posts` **with `source`** | +| **comment** on **$CTO** space | same as post | +| start a space for **$PEPE** | search token → `POST …/communities/{addr}` | +| list all spaces | `GET {SITE}/api/communities` | +| search Bankr tokens **PEPE** | `GET {SITE}/api/tokens/search?q=PEPE` | +| do I hold **TMP**? can I post? | `GET {SITE}/api/holders/{token}?wallet={linked}` | +| react 👍 on post **post_123** in **0x…** | `POST {SITE}/api/posts/post_123/react` | + +**Forbidden:** ask user for skill name · ask wallet if X↔Bankr linked · invent space data without API call · say "can't post to X spaces" or "post manually" (see **NOT-TWITTER-X-SPACES.md**). + +--- + +## Mandatory routing guard + +``` +if message contains "link" OR "url" OR "where is" + space or community/token: + 1. use_skill("bankr-communities") + 2. Read INSTANT-LINK-REPLIES.md + 3. If TMP or ARCHIVE → paste URL from table → STOP (no tools, no HTTP) + 4. Else try GET /api/agent/link?q={TICKER} → paste body + 5. If HTTP fails → known-communities.json → NEVER empty / "couldn't generate" +else if space intent (verify, post, pin, profile, update links, members, latest): + 1. use_skill("bankr-communities") + 2. Read BENEFICIARY-ACTIONS.md (writes) or ONE-LINE-INTENTS.md (reads) + 3. If posting: Read **X-REPLY-POST-CONTENT.md** (what goes in `content`) + **POST-SOURCE.md** → set source.trigger from DM vs tweet vs reply vs terminal + 4. GET /api/holders/{token}?wallet={linked} before writes + 5. Call API — BEFORE replying (posts must include source object) + 6. Plain English reply + communityLink on own line +``` + +**Tweet = DM** — same pipeline. Load skill on `@bankrbot` intake **before** tool selection. + +--- + +## Write actions (linked wallet) + +| Action | Requires | +|--------|----------| +| Create space | Signed-in user, token on Bankr launches | +| Post / comment | **Holder** OR **fee recipient** OR **deployer** (owner can post without holding) | +| React | Holder OR fee recipient OR deployer | +| Verify | Token owner (fee recipient or deployer) | + +`GET /api/holders/{token}?wallet=` returns `canPost: true` for holders **and** owners. + +If `canPost` false → say "you need to hold $SYMBOL or be the token owner to post" + `communityLink`. + +**Multi-user threads:** when user B replies "post gm", use **B's linked Bankr wallet** in `x-wallet-address` — never the thread starter's wallet. + +--- + +## Twitter/X reply rules (MANDATORY) + +X does **not** render markdown links. Every reply **must** include the raw `https://` URL from API `links.communityPage`. + +**Required format (paste `replyText` from API — do not paraphrase without URL):** + +```text +$TMP space — verified · 1 member · 2 posts +latest: "this is from X" by @you + +https://bankr.space/community/0x935e13a28849095db45e63040f109c34b757aba3 +``` + +**Rules:** +- Paste **`replyText`** or **`tweetReply`** from briefing API verbatim — they are identical +- **Never** summarize stats/latest without **`communityLink`** on its own line at the **end** +- Copy `links.communityPage` or `communityLink` if building reply manually — never omit +- Put the full URL on its **own line** (X auto-linkifies it) +- Never end with "view space:" and nothing after it +- Never use only `[View space](url)` markdown — always include the bare URL too +- After posting, include the same space URL again + +--- + +## Success reply templates + +**Briefing:** + +```text +$TMP space — ✓ Verified · 12 members · 34 posts +latest: "@rayblanco.eth shared launch update…" + +https://bankr.space/community/0x935e13a28849095db45e63040f109c34b757aba3 +``` + +**Post:** + +```text +posted to $TMP holder space: "this is from X" + +https://bankr.space/community/0x935e13a28849095db45e63040f109c34b757aba3 +``` + +--- + +## Hub install stack (with TMP) + +```text +install TMP site agent at https://github.com/anondevv69/bankr-tmp-skill/tree/main/tmp-site-agent +install TMP skills at https://github.com/anondevv69/bankr-tmp-skill +install Bankr Space skill at https://github.com/anondevv69/bankr-community/tree/main/skills/bankr-communities +``` + +TMP marketplace ops → TMP skills. Space social layer → **this skill**. + +--- + +## Files + +| File | Purpose | +|------|---------| +| `TERMINOLOGY.md` | **community vs space** — read first | +| `X-REPLY-POST-CONTENT.md` | **X reply: post THIS = parent tweet; explicit text = user words** | +| `POST-SOURCE.md` | **Mandatory `source` on every agent post** (X DM, mention, terminal) | +| `BENEFICIARY-ACTIONS.md` | **Verify, profile, pin, post+pin — tweet + terminal** | +| `INSTANT-LINK-REPLIES.md` | Link questions — paste URL, no HTTP (read first for links) | +| `GET-LINK.md` | GET /api/agent/link for unknown tickers | +| `LINK-INTENT-ONLY.md` | Pointer to GET-LINK.md | +| `ONE-LINE-INTENTS.md` | Full intent table | +| `community-autopilot.md` | Step-by-step execution | +| `references/COMMUNITY-LINK-RULES.md` | **Mandatory link format — never bankr.bot** | +| `references/AGENT-ROUTING-COMMUNITIES.md` | Routing guard | +| `references/BANKR-PLATFORM-TWEET-INTAKE.md` | Platform requirements | +| `references/community-api-reference.md` | All endpoints | diff --git a/bankr-communities/TERMINOLOGY.md b/bankr-communities/TERMINOLOGY.md new file mode 100644 index 0000000000..0526cc9e56 --- /dev/null +++ b/bankr-communities/TERMINOLOGY.md @@ -0,0 +1,53 @@ +# Terminology — community vs space + +**Product name:** Bankr Space (`https://bankr.space`) + +## NOT Twitter/X audio Spaces + +When users say **"post in $PMFI space"** or **"post this in $TICKER space"**, they mean **Bankr Space** — the token-gated feed at `bankr.space/community/0x…`. + +They do **not** mean Twitter/X **audio Spaces** (live rooms). **Never** refuse with "I can't post to X spaces." Load **`bankr-communities`** and call the site API. See **`NOT-TWITTER-X-SPACES.md`**. + +## What agents should say + +| Context | Word | +|---------|------| +| Replies to users | **space** / **spaces** — e.g. "$TMP space", "holder space", "list all spaces" | +| Product | **Bankr Space** (not "Bankr Communities") | +| Link in prose | **space link** or **space URL** | + +## What users may say (same intent) + +Users often say **community** or **space** interchangeably. Treat both as the same token-gated discussion area: + +- "TMP community" = "TMP space" +- "post in CTO community" = "post in CTO space" +- "verify the community" = "verify the space" + +**When replying:** prefer **space** in your wording (API `replyText` already uses "space"). + +## What stays `community` (do not rename) + +These are **API / code names** — use exactly as documented: + +| Keep as-is | Example | +|------------|---------| +| REST paths | `GET /api/communities`, `POST /api/communities/{token}/posts` | +| Agent routes | `/api/agent/resolve-community`, `/api/agent/search-communities` | +| JSON fields | `community`, `communityLink`, `communityExists`, `suggestCreateCommunity` | +| Skill slug | `bankr-communities` | +| Env var | `COMMUNITIES_SITE_URL` | +| Page URL path | `https://bankr.space/community/0x…` (path is `/community/`; call it a **space link** in prose) | + +## Reply templates (from API) + +Paste `replyText` / `tweetReply` verbatim. Format uses **space**: + +```text +$TMP space — verified · 12 members · 34 posts +latest: "gm holders" by @user + +https://bankr.space/community/0x935e13a28849095db45e63040f109c34b757aba3 +``` + +Always end with `communityLink` (full `https://` URL on its own line). diff --git a/bankr-communities/X-REPLY-POST-CONTENT.md b/bankr-communities/X-REPLY-POST-CONTENT.md new file mode 100644 index 0000000000..77e58109b7 --- /dev/null +++ b/bankr-communities/X-REPLY-POST-CONTENT.md @@ -0,0 +1,159 @@ +# X reply → space post content (what to put in `content`) + +When a user **replies on X** to @bankrbot (or mentions in a thread), decide **what text** goes in `POST …/posts` `{ "content": "…" }`. + +**Read this before every X-sourced post write.** Pair with **`POST-SOURCE.md`** (`trigger: x-reply` when user is replying in a thread). + +--- + +## Golden rule + +| User gave explicit post text? | Use for `content` | +|------------------------------|-------------------| +| **No** — only “post **this** / **that** / **it** in $TICKER space” | **Parent tweet** they are replying to (see below) | +| **Yes** — colon, quotes, or clear prose | **User’s text only** — **never** substitute the parent tweet | + +**Explicit always wins** over the parent tweet. + +--- + +## Mode A — implicit (“post this”) + +**User is replying to another tweet** and says things like: + +```text +@bankrbot post this in $TMP space +@bankrbot can you post this in the ARCHIVE space +@bankrbot share this in $BNKR space +@bankrbot put that in $xxx space +``` + +**No colon, no quoted body, no user-authored sentence** — only deictic words (`this`, `that`, `it`, `above`, `what I'm replying to`). + +**Steps:** + +1. Resolve **parent tweet** from X reply context (`in_reply_to`, quoted tweet, or thread parent Bankr exposes). +2. Build `content` from parent (pick **one**, in order): + 1. **Parent status URL** — `https://x.com/{user}/status/{id}` (preferred on bankr.space — renders as **tweet preview card**) + 2. Parent tweet **plain text** (if URL unavailable) + 3. Parent tweet text **+ URL on its own line** (if text is short and URL adds context) +3. `source.trigger` = **`x-reply`** +4. `source.externalRef` = **user’s command tweet id** (the @bankrbot reply), not the parent id + +**Example** + +User replies to `https://x.com/0xtetron/status/2064237962884420005` with: + +```text +@bankrbot post this in $BNKR space +``` + +→ `content`: + +```text +https://x.com/0xtetron/status/2064237962884420005 +``` + +→ `source`: `{ "client": "agent", "trigger": "x-reply", "viaAgent": true, "agentId": "bankrbot", "externalRef": "{user_command_tweet_id}" }` + +--- + +## Mode B — explicit (user’s own words) + +**User supplies the post body.** Do **not** pull parent tweet text or URL. + +### Strong signals (always explicit) + +```text +@bankrbot post in $TMP space: launch update for holders +@bankrbot post "gm holders" in ARCHIVE space +@bankrbot post in BNKR space: xxxxx ewrwe xx test test +``` + +**Colon form:** everything after the **first** `:` (trimmed) is `content`. + +**Quoted form:** text inside `"…"` or `'…'` is `content`. + +### Inline prose (no colon) + +```text +@bankrbot can you post xxxxx ewrwe xx test test in $xxx space as a reply +@bankrbot post hello world test in $TMP space +``` + +**Parse:** extract the **phrase between** `post` (or `comment`) and `in $TICKER` / `in {SYMBOL} space` / `to $TICKER space`. + +→ `content` = `xxxxx ewrwe xx test test` or `hello world test` + +**Do not** append or replace with parent tweet when this pattern matches. + +--- + +## Decision tree (run in order) + +``` +1. User message matches /post in .+:\s*.+/ OR /post ["'].+["']/ ? + → YES: content = text after colon or inside quotes → Mode B → STOP + +2. User message has substantive text between "post" and "in $TICKER" (≥3 chars, not only this/that/it) ? + → YES: content = that phrase → Mode B → STOP + +3. User says post/share/put + (this|that|it|above) + space/ticker ? + → YES: content = parent tweet URL (preferred) or text → Mode A → STOP + +4. User is in X reply thread but wording ambiguous ? + → Prefer Mode B only if you can extract a non-deictic phrase; else Mode A (parent URL) + +5. Never post empty content. Never post parent tweet when user clearly typed their own body. +``` + +--- + +## Deictic words (implicit only) + +Treat as **Mode A** when these are the **only** “content” words: + +`this`, `that`, `it`, `the tweet`, `the post`, `what i'm replying to`, `above`, `below`, `this one` + +If the same message also contains a **colon phrase** or **multi-word user sentence**, use **Mode B** instead. + +--- + +## `source.trigger` for X + +| Situation | `trigger` | +|-----------|-----------| +| User **replied** in a thread (parent tweet exists) | `x-reply` | +| Top-level @mention, no reply parent | `x-mention` | +| DM | `x-dm` | + +--- + +## Tweet examples (acceptance) + +| User tweet (context) | Expected `content` | +|----------------------|---------------------| +| Reply to `0xtetron/…4420005`: `@bankrbot post this in $BNKR space` | `https://x.com/0xtetron/status/2064237962884420005` | +| `@bankrbot post in TMP space: weekly update` | `weekly update` | +| `@bankrbot post xxxxx ewrwe xx test test in $xxx space` | `xxxxx ewrwe xx test test` | +| `@bankrbot post "gm holders" in ARCHIVE space` | `gm holders` | +| Reply + `@bankrbot post in TMP: my own words` | `my own words` (**not** parent tweet) | + +--- + +## After post + +1. `POST …/posts` with `content` + `source` (see **POST-SOURCE.md**) +2. Reply on X with confirmation + **bankr.space/community/0x…** URL (own line) +3. Optional: mention that a status URL in the space will show as a tweet card + +--- + +## Fail rules + +- **Never** use parent tweet when user wrote explicit post text (colon, quotes, or inline phrase). +- **Never** use “this/that” heuristics when user included `post in TICKER: …`. +- **Never** post without `source` on @bankrbot writes. +- If parent tweet unavailable in Mode A → ask once: “Reply with the tweet link or paste the text to post” + space link if known. + +See also: **BENEFICIARY-ACTIONS.md**, **POST-SOURCE.md**, `{SITE}/agent.md` diff --git a/bankr-communities/known-communities.json b/bankr-communities/known-communities.json new file mode 100644 index 0000000000..065e99ae44 --- /dev/null +++ b/bankr-communities/known-communities.json @@ -0,0 +1,30 @@ +{ + "siteUrl": "https://bankr.space", + "COMMUNITIES_SITE_URL": "https://bankr.space", + "urlTemplate": "https://bankr.space/community/{tokenContractAddress}", + "linkApiTemplate": "https://bankr.space/api/agent/link?q={TICKER}", + "linkApiExamples": { + "TMP": "https://bankr.space/api/agent/link?q=TMP", + "ARCHIVE": "https://bankr.space/api/agent/link?q=ARCHIVE" + }, + "communities": { + "TMP": { + "symbol": "TMP", + "tokenAddress": "0x935e13a28849095db45e63040f109c34b757aba3", + "communityLink": "https://bankr.space/community/0x935e13a28849095db45e63040f109c34b757aba3", + "linkApi": "https://bankr.space/api/agent/link?q=TMP" + }, + "ARCHIVE": { + "symbol": "ARCHIVE", + "tokenAddress": "0x76aba8089e4ba07f705fb886d17dd41793ad2ba3", + "communityLink": "https://bankr.space/community/0x76aba8089e4ba07f705fb886d17dd41793ad2ba3", + "linkApi": "https://bankr.space/api/agent/link?q=ARCHIVE" + }, + "PMFI": { + "symbol": "PMFI", + "tokenAddress": "0xd77ce6d3137342bb5174673bdab5f51db16fcba3", + "communityLink": "https://bankr.space/community/0xd77ce6d3137342bb5174673bdab5f51db16fcba3", + "linkApi": "https://bankr.space/api/agent/link?q=PMFI" + } + } +} diff --git a/bankr-communities/references/agent-guide.md b/bankr-communities/references/agent-guide.md new file mode 100644 index 0000000000..b356df712a --- /dev/null +++ b/bankr-communities/references/agent-guide.md @@ -0,0 +1,64 @@ +# Bankr Space — agent guide + +**Human site:** https://bankr.space (Vercel Next.js app in `web/`) + +**Live mirror for humans and other bots:** `{YOUR_VERCEL_URL}/agent.md` (same content as `web/content/agent.md`) + +When editing, update **`web/content/agent.md`** then redeploy. Keep this file in sync. + +**Terminology:** Read **`TERMINOLOGY.md`** — users may say **community** or **space** (same intent); agent replies use **space**; API/JSON keeps `community`, `communityLink`, `/api/communities`. + +--- + +## Golden rules + +1. **One sentence → full flow** — no "open the website" if API works. +2. **Briefing first** — `GET /api/agent/briefing` for "latest / members / opportunities". +3. **Post / react gate** — `GET /api/holders/{token}?wallet=` → `canPost` for holders **or** owner. +4. **Owner verify** — only fee recipient / deployer. +5. **Reply with links** — paste `replyText` or `communityLink`; full space URL on its own line. + +--- + +## Intent → API + +| User says (community or space) | First call | +|-----------|------------| +| Latest on $TMP | `/api/agent/briefing?symbol=TMP` | +| Member count | briefing → stats.memberCount | +| Post in space / community | holders check → POST posts **with `source`** (POST-SOURCE.md) | +| Verify space / community | POST verify | +| Create space / community | search → POST `/api/communities/{token}` | +| List all spaces | GET /api/communities | +| Space / community link | `GET /api/agent/link?q=TICKER` or INSTANT-LINK-REPLIES.md for TMP/ARCHIVE | + +Full table: **`ONE-LINE-INTENTS.md`** + +--- + +## Install with TMP stack + +```text +install TMP site agent at https://github.com/anondevv69/bankr-tmp-skill/tree/main/tmp-site-agent +install TMP skills at https://github.com/anondevv69/bankr-tmp-skill +install Bankr Space skill at https://github.com/anondevv69/bankr-community/tree/main/skills/bankr-communities +``` + +Set `COMMUNITIES_SITE_URL` on Bankr only if overriding the default `https://bankr.space`. + +--- + +## Execution + +| File | Purpose | +|------|---------| +| `TERMINOLOGY.md` | **community vs space** — read first | +| `ONE-LINE-INTENTS.md` | Intent → API table | +| `BENEFICIARY-ACTIONS.md` | Verify, profile, pin, post+pin | +| `INSTANT-LINK-REPLIES.md` | TMP/ARCHIVE links — no HTTP | +| `community-autopilot.md` | Step-by-step flows | +| `references/AGENT-ROUTING-COMMUNITIES.md` | Routing guard | +| `references/BANKR-PLATFORM-TWEET-INTAKE.md` | Tweet intake | +| `references/community-api-reference.md` | All endpoints | + +Public guide (canonical): **`https://bankr.space/agent.md`** diff --git a/bankr-communities/references/agent-routing-communities.md b/bankr-communities/references/agent-routing-communities.md new file mode 100644 index 0000000000..0e0989a567 --- /dev/null +++ b/bankr-communities/references/agent-routing-communities.md @@ -0,0 +1,51 @@ +# Agent routing — Bankr Space + +> Load with skill install. Overrides generic "I don't know about spaces" replies. + +**First:** Read **`NOT-TWITTER-X-SPACES.md`** — "post in $TICKER space" is **bankr.space**, not Twitter audio Spaces. + +## TRIGGER + +**Link (highest priority):** link, URL, "where is the space" → **`INSTANT-LINK-REPLIES.md`** first (TMP/ARCHIVE need no HTTP). + +**Writes (same routing as post-in-space):** verify, post, pin, update profile, add links → **`BENEFICIARY-ACTIONS.md`**. + +**Other reads:** space (user may say community), members, posts, latest on $TICKER space, start space. + +**Load:** `bankr-communities` → **`INSTANT-LINK-REPLIES.md`** (links) or **`ONE-LINE-INTENTS.md`** (everything else). + +--- + +## ROUTING GUARD + +``` +if message matches link intent: + 1. use_skill("bankr-communities") + 2. TMP or ARCHIVE mentioned → paste instant URL from INSTANT-LINK-REPLIES.md → STOP + 3. Other ticker → GET /api/agent/link?q=… → paste body + 4. NEVER "I wasn't able to generate a response" + +if message matches other space intent: + 1. use_skill("bankr-communities") + 2. GET /api/agent/briefing or specific endpoint + 3. Include communityLink (NEVER bankr.bot) +``` + +--- + +## Hard rules + +1. **Link for TMP/ARCHIVE** — instant paste, no tool call required. +2. **Never** skip API call for stats/posts/members (non-link intents). +3. **Never** require `use_skill` in user tweet text. +4. **Never** link `bankr.bot` or `t.co` for communities. +5. **Tweet = DM** — same skill load order. + +--- + +## TMP coexistence + +| Intent | Route to | +|--------|----------| +| claim fees, list, buy, launch | TMP skills | +| space social | **this skill** | diff --git a/bankr-communities/references/bankr-platform-tweet-intake.md b/bankr-communities/references/bankr-platform-tweet-intake.md new file mode 100644 index 0000000000..367acb8e99 --- /dev/null +++ b/bankr-communities/references/bankr-platform-tweet-intake.md @@ -0,0 +1,88 @@ +# Bankr platform — tweet intake for Bankr Space skill + +> **Audience:** Bankr engineering. Skill content is correct if loaded; tweets fail when skill is not in execution path. + +--- + +## User tweet wording (sufficient TRIGGER) + +```text +@bankrbot what's the latest on the TMP space? +@bankrbot how many members in CTO space? +@bankrbot post in TMP space: hello holders +@bankrbot verify the TMP space +@bankrbot add website https://example.com to TMP space profile +@bankrbot post in TMP space: hello holders — pin it +@bankrbot pin the latest post in TMP space +``` + +Users must **NOT** need: `use_skill bankr-communities`, API paths, or wallet paste (if X↔Bankr linked). + +--- + +## Required platform behavior + +On tweet/DM matching space intent (user may say community): + +``` +1. MATCH trigger (link, verify, post in, pin, update profile, add links, members, latest on $TICKER) +2. use_skill("bankr-communities") ← BEFORE tool selection +3. Writes → BENEFICIARY-ACTIONS.md → GET /api/holders?wallet= → POST/PATCH/pin-post +4. Link question → GET /api/agent/link?q={TICKER} or instant table +5. Other reads → GET /api/agent/briefing?... +6. Plain English reply + **bankr.space/community/0x{contract}** URL +``` + +**Write acceptance test:** `@bankrbot verify the TMP space` +Must log: `POST …/api/communities/0x935e…/verify` with linked wallet header. + +**Write acceptance test:** `@bankrbot post in TMP space: update — pin it` +Must log: `POST …/posts` **with `source`** (see POST-SOURCE.md) then `POST …/pin-post` if verified beneficiary. + +**Write acceptance test (X reply — implicit):** User replies to a status with `@bankrbot post this in $BNKR space` +Must log: `POST …/posts` with `content` = parent status URL, `source.trigger` = `x-reply`. See **X-REPLY-POST-CONTENT.md**. + +**Write acceptance test (explicit inline text):** `@bankrbot post xxxxx ewrwe xx test test in $xxx space` +Must log: `POST …/posts` with `content` = `xxxxx ewrwe xx test test` — **not** parent tweet. + +**Link acceptance test:** `@bankrbot what's the link to the TMP space?` + +Must log: `GET …/api/agent/link?q=TMP` +Must reply: `https://bankr.space/community/0x935e13a28849095db45e63040f109c34b757aba3` + +**Fail:** "I wasn't able to generate a response" (use known-communities.json fallback instead) + +**Same pipeline for tweet and DM.** + +--- + +## Acceptance test + +**Tweet:** `@bankrbot how many members in TMP space?` + +**Pass:** +- Log shows skill load before reply +- `GET …/api/agent/briefing?symbol=TMP` +- Reply: "TMP space has N members, M posts…" + link + +**Fail:** +- Generic "I can't access communities" +- **"I don't have the ability to post to X spaces"** — wrong product; means **bankr.space** (see **NOT-TWITTER-X-SPACES.md**) +- No HTTP call to communities site +- Asks user to install skill manually + +**Production failure example (must NOT repeat):** + +Tweet: `@bankrbot post this in $pmfi space` (reply to a status) + +Wrong reply: "I don't have the ability to post to X spaces or communities directly… post manually." + +Pass: skill load → `POST …/communities/0xd77ce6d3137342bb5174673bdab5f51db16fcba3/posts` with parent status URL + confirmation + space link. + +--- + +## Env + +Bankr agent wallet / deployment should set: + +`COMMUNITIES_SITE_URL=https://bankr.space` (optional — this is the skill default) diff --git a/bankr-communities/references/beneficiary-actions.md b/bankr-communities/references/beneficiary-actions.md new file mode 100644 index 0000000000..e18f82414a --- /dev/null +++ b/bankr-communities/references/beneficiary-actions.md @@ -0,0 +1,178 @@ +# Beneficiary actions — verify, profile, pin (tweet + terminal) + +> Same pipeline as **post in space**. User does NOT need to say `use_skill`. Load `bankr-communities` → call API → plain English reply + space URL. + +**Site:** `https://bankr.space` +**Writes:** header `x-wallet-address: {user's linked Bankr wallet}` — never the thread starter's wallet. + +--- + +## Who can do what + +| Action | Who | Space must be verified? | +|--------|-----|----------------------------| +| **Verify** | Fee beneficiary only | No (this creates verified) | +| **Update profile / social links** | Fee beneficiary only | No | +| **Post / comment** | Holder OR beneficiary OR deployer | No | +| **Pin / unpin post** | Fee beneficiary only | **Yes** | + +Check before writes: + +```http +GET /api/holders/{tokenAddress}?wallet={linked} +``` + +Use: `canEditProfile`, `canPinPosts`, `canPost`, `isBeneficiary`. + +--- + +## Verify space + +**User says:** +```text +@bankrbot verify the TMP space +@bankrbot verify space for $TMP +``` + +**Steps:** +``` +1. GET /api/agent/briefing?symbol=TMP → get tokenAddress, community.verified +2. If already verified → "TMP space is already verified" + communityLink → STOP +3. POST /api/communities/{tokenAddress}/verify + Header: x-wallet-address: {linked} +4. Reply: "Verified $TMP space ✓" + communityLink on its own line → STOP +5. 403 → "Only the token fee beneficiary can verify" + communityLink +``` + +--- + +## Update profile / add social links + +**User says:** +```text +@bankrbot add website https://tokenmarketplace.shop to TMP space +@bankrbot update TMP space profile: website tokenmarketplace.shop telegram t.me/tmp +@bankrbot set TMP space description: Token marketplace for holders +@bankrbot add these links to TMP token info: x @MyToken github myorg/repo +``` + +**Editable fields:** `description`, `socialLinks.x`, `socialLinks.website`, `socialLinks.github`, `socialLinks.telegram`, `socialLinks.discord` + +**NOT editable via API:** beneficiary wallet (from Bankr launch data). + +**Steps:** +``` +1. GET /api/holders/{token}?wallet={linked} → if !canEditProfile → 403 message → STOP +2. GET /api/communities/{tokenAddress} → read current description + socialLinks +3. Merge user-requested fields into body (keep existing fields not mentioned) +4. PATCH /api/communities/{tokenAddress} + Body: { "description": "...", "socialLinks": { "website": "...", "x": "...", ... } } + Header: x-wallet-address: {linked} +5. Reply: "Updated $TMP space profile" + list what changed + communityLink → STOP +``` + +**PATCH body example:** +```json +{ + "description": "Token Market Place for holders.", + "socialLinks": { + "website": "https://tokenmarketplace.shop", + "x": "https://x.com/MyToken", + "telegram": "https://t.me/mytoken", + "discord": "https://discord.gg/mytoken" + } +} +``` + +--- + +## Pin a post + +**User says:** +```text +@bankrbot pin post post_123 in TMP space +@bankrbot unpin post post_123 in TMP space +@bankrbot pin the latest post in TMP space +``` + +**Steps:** +``` +1. GET /api/holders/{token}?wallet={linked} → if !canPinPosts → "Verify space first / beneficiary only" → STOP +2. Resolve postId (from message, or GET /api/communities/{token} → latest post id) +3. POST /api/communities/{tokenAddress}/pin-post + Body: { "postId": "post_123", "action": "pin" | "unpin" } + Header: x-wallet-address: {linked} +4. Reply: "Pinned post in $TMP space" (most recent pin shows first) + communityLink → STOP +``` + +--- + +## Post AND pin (combined) + +**User says:** +```text +@bankrbot post in TMP space: launch update — and pin it +@bankrbot post in TMP space: gm holders then pin +``` + +**Steps:** +``` +1. GET /api/holders/{token}?wallet={linked} → if !canPost → explain holder/owner required → STOP +2. POST /api/communities/{tokenAddress}/posts + body: { + "content": "...", + "source": { + "client": "agent", + "trigger": "x-dm | x-mention | x-reply | terminal", + "viaAgent": true, + "agentId": "bankrbot", + "externalRef": "{id_if_known}" + } + } + headers: x-wallet-address, x-client: agent + → save postId from response + See POST-SOURCE.md for trigger selection. +3. If user asked to pin: + - GET /api/holders/{token}?wallet={linked} again → if canPinPosts: + POST /api/communities/{tokenAddress}/pin-post body: { "postId": "{postId}", "action": "pin" } + - else: confirm post but say "Only verified beneficiary can pin — post is live unpinned" +4. Reply: paste post replyText from step 2 + "pinned ✓" if step 3 ran → STOP +``` + +--- + +## Tweet examples (copy-paste tests) + +```text +@bankrbot verify the TMP space +@bankrbot add website https://tokenmarketplace.shop to TMP space profile +@bankrbot post in TMP space: big update for holders — pin it +@bankrbot pin the latest post in TMP space +@bankrbot post in ARCHIVE space: gm +``` + +--- + +## Reply format (every write) + +```text +posted to $TMP holder space: "launch update" +pinned ✓ + +https://bankr.space/community/0x935e13a28849095db45e63040f109c34b757aba3 +``` + +Always include **communityLink** on its own line. Never `bankr.bot`. + +--- + +## Routing (Bankr platform) + +These phrases MUST load `bankr-communities` **before** tool selection — same as `post in space`: + +- verify space / verify $TICKER +- update profile / add links / add website / set description + space/community or token +- pin post / pin it / unpin + space/community +- post in space + pin + +**Fail:** generic "I wasn't able to generate a response" without calling API. diff --git a/bankr-communities/references/community-api-reference.md b/bankr-communities/references/community-api-reference.md new file mode 100644 index 0000000000..a5669782b2 --- /dev/null +++ b/bankr-communities/references/community-api-reference.md @@ -0,0 +1,121 @@ +# Bankr Space site API reference (agent) + +**Base:** `https://bankr.space` (default; override with `COMMUNITIES_SITE_URL`) + +All responses JSON. Writes require header **`x-wallet-address: 0x…`** (linked Bankr wallet). + +--- + +## Agent resolve & search (links) + +``` +GET /api/agent/link?q=TMP ← plain text reply (preferred for link questions) +GET /api/agent/link?q=ARCHIVE +GET /api/agent/resolve-community?q=TMP ← JSON with communityLink / tweetReply +GET /api/agent/resolve-community?q=TMP&format=text +GET /api/agent/search-communities?q=archive +``` + +**link (plain text):** response body = tweet reply. Same as `curl "…/api/agent/link?q=TMP"`. No JSON parsing. + +**resolve-community:** search existing spaces → if found `communityLink` → if token on Bankr but no space `suggestCreateCommunity: true` + ask to create → on yes POST `/api/communities/{tokenAddress}`. + +**search-communities:** list only spaces already created matching query matching query. + +--- + +## Agent briefing (start here) + +``` +GET /api/agent/briefing?symbol=TMP +GET /api/agent/briefing?token=0x935e13a28849095db45e63040f109c34b757aba3 +GET /api/agent/briefing?q=search term +``` + +Returns: `community`, `stats`, `recentPosts`, `opportunities`, `links`, `agentActions`. + +--- + +## Spaces (API) + +``` +GET /api/communities +GET /api/communities/{tokenAddress} +PATCH /api/communities/{tokenAddress} body: { description?, socialLinks? } ← fee beneficiary +POST /api/communities/{tokenAddress} body: { description? } +POST /api/communities/{tokenAddress}/verify +POST /api/communities/{tokenAddress}/posts body: { content, source? } → returns postId +``` + +**Post `source` (optional provenance):** + +| Field | Values | +|-------|--------| +| `client` | `web`, `bankr-app`, `agent`, `api` (or header `x-client`) | +| `trigger` | `manual`, `x-dm`, `x-mention`, `x-reply`, `terminal`, `autopilot` | +| `viaAgent` | boolean | +| `agentId` | e.g. `bankrbot` | +| `externalRef` | tweet/DM id | + +Agents posting after an X DM should set `client: agent`, `trigger: x-dm`, `viaAgent: true`, `agentId: bankrbot`. UI shows e.g. **Posted via @bankrbot · X DM**. + +**Mandatory for @bankrbot:** every post write includes `source`. Read **`POST-SOURCE.md`** (skill root). + +``` +POST /api/communities/{tokenAddress}/pin-post body: { postId, action: "pin"|"unpin" } +``` + +**PATCH socialLinks fields:** `x`, `website`, `github`, `telegram`, `discord` (beneficiary wallet is read-only from Bankr). + +**pin-post:** verified fee beneficiary only. Multiple pins allowed; most recent pin shows first. + +**holders check before writes:** +``` +GET /api/holders/{tokenAddress}?wallet=0x… +→ canPost, canEditProfile, canPinPosts, isBeneficiary +``` + +--- + +## Tokens & holders + +``` +GET /api/tokens/search?q=PEPE +GET /api/holders/{tokenAddress}?wallet=0x… +``` + +--- + +## Reactions + +``` +POST /api/posts/{postId}/react +body: { tokenAddress, reaction: "👍" | "❤️" | "🔥" } +``` + +--- + +## Cron (owner / platform) + +``` +POST /api/cron/sync-tokens +Header: Authorization: Bearer {CRON_SECRET} +``` + +--- + +## Bankr API (server-side, no communities site) + +Token launches also available at `https://api.bankr.bot/token-launches` — communities site caches these hourly. + +--- + +## Error codes + +| Status | Meaning | +|--------|---------| +| 401 | Wallet header missing | +| 403 | Not holder / not owner | +| 404 | Space not found | +| 409 | Space already exists | +| 503 | KV not configured | diff --git a/bankr-communities/references/community-autopilot.md b/bankr-communities/references/community-autopilot.md new file mode 100644 index 0000000000..2f977f7e2c --- /dev/null +++ b/bankr-communities/references/community-autopilot.md @@ -0,0 +1,115 @@ +# Space autopilot — Bankr agent execution + +**Load:** `bankr-communities` skill + this file. + +**Env:** `COMMUNITIES_SITE_URL` — optional override. **Default site:** `https://bankr.space` + +--- + +## Flow A — Briefing ("what's latest?") + +| Step | Action | +|------|--------| +| 1 | Resolve token: `0x…` from message, or symbol `$TMP` → `symbol=TMP`, or name | +| 2 | `GET {SITE}/api/agent/briefing?symbol=TMP` (or `?token=0x…`) | +| 3 | Paste **`replyText`** verbatim — **last line is the URL**. Do not summarize without `communityLink` | +| 4 | Mention `opportunities[]` if any (unverified, no posts, no space yet) | +| 5 | **NEVER ask user for site URL** — **STOP** | + +--- + +## Flow B — Create space + +| Step | Action | +|------|--------| +| 1 | Resolve token address via `GET /api/tokens/search?q=` | +| 2 | Confirm not already in `GET /api/communities` | +| 3 | `POST {SITE}/api/communities/{tokenAddress}` body `{ "description": "…" }` header `x-wallet-address: {linked}` | +| 4 | If `autoVerified: true` → say owner auto-verified | +| 5 | Reply with space URL — **STOP** | + +--- + +## Flow C — Verify space (owner only) + +| Step | Action | +|------|--------| +| 1 | `GET /api/agent/briefing?symbol=…` — confirm space exists, not verified | +| 2 | `POST {SITE}/api/communities/{token}/verify` header `x-wallet-address: {linked}` | +| 3 | Success → "Verified $SYMBOL space" — **STOP** | +| 4 | 403 → "Only token owner can verify" — **STOP** | + +--- + +## Flow D — Post / comment (holders only) + +| Step | Action | +|------|--------| +| 1 | Resolve space token address (from briefing) | +| 2 | `GET {SITE}/api/holders/{token}?wallet={linked}` | +| 3 | If `!canPost` → explain holder OR owner required + `communityLink` — **STOP** | +| 4 | `POST {SITE}/api/communities/{token}/posts` `{ "content": "…", "source": { … } }` — **required `source`** per **`POST-SOURCE.md`** — header `x-wallet-address: {linked}`, `x-client: agent` | +| 5 | Confirm post + paste `links.communityPage` URL on its own line — **STOP** | + +--- + +## Flow E — React + +| Step | Action | +|------|--------| +| 1 | Parse postId + token + emoji (👍 ❤️ 🔥) | +| 2 | Holder check (Flow D step 2–3) | +| 3 | `POST {SITE}/api/posts/{postId}/react` `{ tokenAddress, reaction }` | +| 4 | Confirm — **STOP** | + +--- + +## Flow F — List / search + +| Step | Action | +|------|--------| +| 1 | `GET {SITE}/api/communities` or `GET /api/tokens/search?q=` | +| 2 | Format as short list with symbols + member counts — **STOP** | + +--- + +## Flow G — Update profile / social links (beneficiary only) + +| Step | Action | +|------|--------| +| 1 | `GET /api/holders/{token}?wallet={linked}` → if `!canEditProfile` → **STOP** | +| 2 | `GET /api/communities/{token}` → current `description` + `socialLinks` | +| 3 | Merge user fields → `PATCH /api/communities/{token}` `{ description?, socialLinks? }` | +| 4 | Confirm changes + `communityLink` — **STOP** | + +Full examples: **`BENEFICIARY-ACTIONS.md`** + +--- + +## Flow H — Pin / unpin post (verified beneficiary only) + +| Step | Action | +|------|--------| +| 1 | `GET /api/holders/{token}?wallet={linked}` → if `!canPinPosts` → **STOP** | +| 2 | Resolve `postId` from message or latest post | +| 3 | `POST /api/communities/{token}/pin-post` `{ postId, action: "pin"|"unpin" }` | +| 4 | Confirm + `communityLink` — **STOP** | + +--- + +## Flow I — Post then pin (combined) + +| Step | Action | +|------|--------| +| 1 | Flow D steps 1–4 (post) → save `postId` | +| 2 | If user said pin/pin it → Flow H on that `postId` if `canPinPosts` | +| 3 | Reply with post confirmation + pinned note + URL — **STOP** | + +--- + +## Self-check + +1. Did you call briefing API before answering "latest"? → **YES** +2. Did you check holder before post? → **YES** +3. Did you use linked wallet header for writes? → **YES** +4. Is tweet pipeline same as DM? → **YES** diff --git a/bankr-communities/references/community-link-rules.md b/bankr-communities/references/community-link-rules.md new file mode 100644 index 0000000000..bdb57a1f40 --- /dev/null +++ b/bankr-communities/references/community-link-rules.md @@ -0,0 +1,76 @@ +# Space link rules — MANDATORY for every Bankr reply + +## The only valid space URL format + +```text +https://bankr.space/community/{tokenContractAddress} +``` + +Replace `{tokenContractAddress}` with the token's **on-chain contract address** (0x + 40 hex chars). + +**Never use the ticker/symbol in the path.** Wrong: `/community/TMP` or `/community/ARCHIVE`. + +--- + +## Examples (copy exactly) + +| Token | Contract | Space link | +|-------|----------|----------------| +| $TMP | `0x935e13a28849095db45e63040f109c34b757aba3` | `https://bankr.space/community/0x935e13a28849095db45e63040f109c34b757aba3` | +| $ARCHIVE | `0x76aba8089e4ba07f705fb886d17dd41793ad2ba3` | `https://bankr.space/community/0x76aba8089e4ba07f705fb886d17dd41793ad2ba3` | + +--- + +## How to get the link (always call API — never guess) + +```http +GET https://bankr.space/api/agent/link?q=TMP +GET https://bankr.space/api/agent/link?q=ARCHIVE +``` + +Response is **plain text** — paste the entire body as the tweet reply (same as terminal curl). + +JSON alternative: + +```http +GET https://bankr.space/api/agent/resolve-community?q=ARCHIVE +``` + +Use the `communityLink` field from JSON if needed. + +For "what's the link?" → tweet reply = **only** `communityLink`, nothing else. + +For TMP/ARCHIVE on tweet intake, use **`references/instant-link-replies.md`** (no HTTP required). + +--- + +## FORBIDDEN links (never share these for spaces) + +- `https://bankr.bot` or `bankr.bot` +- `https://t.co/...` (Bankr homepage shortlinks) +- `/community/$TICKER` (symbol in path) +- Any URL not starting with `https://bankr.space/community/0x` + +Spaces live on **bankr.space**, not bankr.bot. + +--- + +## Reply templates + +**Link only:** +```text +https://bankr.space/community/0x76aba8089e4ba07f705fb886d17dd41793ad2ba3 +``` + +**Briefing + link:** +```text +$ARCHIVE space — unverified · 1 member · 2 posts +https://bankr.space/community/0x76aba8089e4ba07f705fb886d17dd41793ad2ba3 +latest: "archive the place..." by @Rayblancoeth +``` + +**Post confirmation:** +```text +posted to $ARCHIVE holder space: "gm" +https://bankr.space/community/0x76aba8089e4ba07f705fb886d17dd41793ad2ba3 +``` diff --git a/bankr-communities/references/dm-intents.md b/bankr-communities/references/dm-intents.md new file mode 100644 index 0000000000..3b89b3ebe9 --- /dev/null +++ b/bankr-communities/references/dm-intents.md @@ -0,0 +1,49 @@ +# DM / terminal — space intents + +**Plain language:** see **`ONE-LINE-INTENTS.md`**. + +--- + +## Read intents (no signing) + +| User asks | Agent | +|-----------|-------| +| What's new in $TMP space? | briefing API | +| How many members? | briefing → memberCount | +| Show recent posts | GET `/api/communities/{token}` + posts | +| List spaces | GET /api/communities | +| Find token PEPE on Bankr | GET /api/tokens/search | + +--- + +## Write intents (linked wallet) + +| User asks | Agent | +|-----------|-------| +| Create space for $X | search → POST `/api/communities/{token}` | +| Verify $X space / community | POST verify (owner) | +| Post "…" in $X space / community | holder check → POST post **with `source`** (POST-SOURCE.md) | +| React 👍 to post | holder check → POST react | + +--- + +## Portfolio-style questions + +| Question | API | +|----------|-----| +| Which communities exist for tokens I launched? | GET communities + filter by ownerWallet | +| Can I post in $TMP? | GET holders?wallet={linked} | +| Is $TMP space verified? | briefing → community.verified | + +--- + +## Multi-skill threads + +User may combine TMP + communities in one session: + +```text +claim fees for CTO +what's the latest in CTO space? +``` + +Run TMP skill for claim, then Bankr Space skill for briefing — same linked wallet. diff --git a/bankr-communities/references/get-link.md b/bankr-communities/references/get-link.md new file mode 100644 index 0000000000..ffdc9df278 --- /dev/null +++ b/bankr-communities/references/get-link.md @@ -0,0 +1,67 @@ +# GET link — run exactly like terminal curl + +> **Highest priority.** User asks for a space **link** (may say community), **URL**, or **where is** $TICKER space (or community). + +## Do this (3 steps) + +``` +1. Extract ticker from user message (strip $ and "community" words) + Example: "what's the link to the TMP space?" → TMP + +2. HTTP GET (same as terminal curl): + https://bankr.space/api/agent/link?q=TMP + + Bankr terminal equivalent: + curl "https://bankr.space/api/agent/link?q=TMP" + + Bankr script equivalent: + const body = await http.fetch('https://bankr.space/api/agent/link?q=TMP'); + +3. Tweet reply = response body verbatim. One line. Do not add text before or after. +``` + +**The API returns plain text — not JSON.** The entire response body is what you paste in the tweet. + +--- + +## Examples + +| User says | GET URL | Tweet reply (response body) | +|-----------|---------|----------------------------| +| link to **TMP** space | `.../api/agent/link?q=TMP` | `https://bankr.space/community/0x935e13a28849095db45e63040f109c34b757aba3` | +| link to **ARCHIVE** | `.../api/agent/link?q=ARCHIVE` | `https://bankr.space/community/0x76aba8089e4ba07f705fb886d17dd41793ad2ba3` | +| token exists, no space yet | `.../api/agent/link?q=FOO` | `No $FOO space yet — TokenName is on Bankr. Would you like me to create the space?` | + +Replace `TMP` with whatever ticker/name/address the user asked for. + +--- + +## If HTTP GET fails — use fallback (never fail silently) + +Read `known-communities.json`. Never reply "I wasn't able to generate a response." + +| Symbol | communityLink | +|--------|---------------| +| TMP | `https://bankr.space/community/0x935e13a28849095db45e63040f109c34b757aba3` | +| ARCHIVE | `https://bankr.space/community/0x76aba8089e4ba07f705fb886d17dd41793ad2ba3` | + +--- + +## JSON alternative (if you need fields) + +```http +GET https://bankr.space/api/agent/resolve-community?q=TMP +``` + +Use field `communityLink` or `tweetReply` from JSON. + +Plain text is preferred: `GET .../api/agent/link?q=TMP` + +--- + +## FORBIDDEN + +- `bankr.bot`, `t.co`, `/community/TMP` (symbol in path) +- Empty reply or "I wasn't able to generate a response" +- FAQ when user only asked for a link +- Inventing URLs without GET or known-communities fallback diff --git a/bankr-communities/references/instant-link-replies.md b/bankr-communities/references/instant-link-replies.md new file mode 100644 index 0000000000..1a35b288dd --- /dev/null +++ b/bankr-communities/references/instant-link-replies.md @@ -0,0 +1,33 @@ +# Instant link replies — NO HTTP, NO TOOLS + +> **Tweet intake often cannot run http.fetch.** For known tokens, reply from this table **immediately**. Do not call tools first. Never reply "I wasn't able to generate a response." + +## Match user message → paste this line only + +| If message mentions | Reply (exactly one line) | +|---------------------|--------------------------| +| **TMP** + link / url / space | `https://bankr.space/community/0x935e13a28849095db45e63040f109c34b757aba3` | +| **ARCHIVE** + link / url / space | `https://bankr.space/community/0x76aba8089e4ba07f705fb886d17dd41793ad2ba3` | +| **PMFI** + link / url / space | `https://bankr.space/community/0xd77ce6d3137342bb5174673bdab5f51db16fcba3` | + +Examples that match TMP row: +- "what's the link to the TMP space?" +- "TMP community url" +- "where is $TMP space" + +## Other tickers (HTTP only if instant table miss) + +```http +GET https://bankr.space/api/agent/link?q=PEPE +``` + +Paste response body. If HTTP fails → say token not found or ask to create — **never** empty error. + +## Why two paths + +| Context | What works | +|---------|------------| +| Bankr **terminal** | `http.fetch` / curl → API works | +| Bankr **tweet** | Skill may not run HTTP → use **instant table** above for TMP/ARCHIVE | + +**Terminal and tweet must give the same URL for TMP.** diff --git a/bankr-communities/references/link-intent-only.md b/bankr-communities/references/link-intent-only.md new file mode 100644 index 0000000000..10a47c2347 --- /dev/null +++ b/bankr-communities/references/link-intent-only.md @@ -0,0 +1,11 @@ +# Link questions — read INSTANT-LINK-REPLIES.md first + +> **Tweet intake:** paste URL from skill table — **no HTTP required** for TMP/ARCHIVE. + +**TMP:** `https://bankr.space/community/0x935e13a28849095db45e63040f109c34b757aba3` + +**ARCHIVE:** `https://bankr.space/community/0x76aba8089e4ba07f705fb886d17dd41793ad2ba3` + +Other tickers → `GET-LINK.md` (curl / http.fetch). + +Never reply "I wasn't able to generate a response." diff --git a/bankr-communities/references/one-line-intents.md b/bankr-communities/references/one-line-intents.md new file mode 100644 index 0000000000..16a4029e34 --- /dev/null +++ b/bankr-communities/references/one-line-intents.md @@ -0,0 +1,81 @@ +# One-line intents — Bankr Space + +> User gives **one sentence** → agent runs **full flow** without interview. + +**Site base:** `https://bankr.space` (or `{COMMUNITIES_SITE_URL}` env override) + +--- + +## Read-only (no wallet tx) + +| User says | API | Reply | +|-----------|-----|-------| +| what's the link to **$TMP** space? | `GET /api/agent/link?q=TMP` → paste response body (plain text URL) | +| search live spaces **archive** | `GET /api/agent/search-communities?q=archive` | +| what's the latest on **$TMP** space? | briefing → paste **`replyText` verbatim** (URL on **last** line) | +| how many **members** in **CTO** space? | `GET /api/agent/briefing?symbol=CTO` → `stats.memberCount` | "N members in $CTO space" | +| show **recent posts** for **0x935e…** | `GET /api/communities/0x935e…` | summarize last 5 posts | +| **list** all spaces | `GET /api/communities` | count + top symbols | +| search Bankr token **PEPE** | `GET /api/tokens/search?q=PEPE` | launches found | +| is there a space for **$TMP**? | `GET /api/agent/briefing?symbol=TMP` | yes/no + link | +| what **opportunities** on spaces? | briefing → `opportunities[]` | unverified, first post, create space | + +--- + +## Write (linked wallet + API) + +| User says | Flow | +|-----------|------| +| **start** / **create** space for **$TMP** | search → `POST /api/communities/{token}` `{ description? }` + header `x-wallet-address: {linked}` | +| **verify** **$TMP** space | `GET /api/holders/{token}?wallet={linked}` → `POST /api/communities/{token}/verify` (fee beneficiary) | +| **update** / **add links** to **$TMP** profile | `GET /api/communities/{token}` → merge → `PATCH /api/communities/{token}` `{ description, socialLinks }` (beneficiary) | +| **pin** post in **TMP** / **pin it** after post | `POST /api/communities/{token}/pin-post` `{ postId, action: "pin" }` (verified beneficiary) | +| **post** in **TMP** space: {text} **and pin** | post → then pin-post if `canPinPosts` | +| **post** in **TMP** space: {text} | holder check → **X-REPLY-POST-CONTENT.md** → `POST …/posts` **with `source`** | +| **post this** in **$BNKR** space (X reply to a tweet) | **X-REPLY-POST-CONTENT.md** → parent status URL as `content` | +| **post** {inline text} in **$xxx** space (no colon) | **X-REPLY-POST-CONTENT.md** → inline text only, not parent tweet | +| **comment** in **0x935e…** space: {text} | same as post | +| react **👍** on post **{id}** in **TMP** | `POST /api/posts/{id}/react` `{ tokenAddress, reaction: "👍" }` | + +--- + +## Tweet examples (sufficient — no "use skill") + +```text +@bankrbot what's the latest on the TMP space? +@bankrbot what's the latest on the TMP community? ← same intent +@bankrbot verify the TMP space +@bankrbot add website https://tokenmarketplace.shop to TMP space profile +@bankrbot post in TMP space: launch update — pin it +@bankrbot pin the latest post in TMP space +@bankrbot post in TMP space: gm holders +@bankrbot post this in BNKR space +@bankrbot post xxxxx ewrwe xx test test in $xxx space +@bankrbot start a space for 0x935e13a28849095db45e63040f109c34b757aba3 +``` + +--- + +## Forbidden + +- Reply without calling site API first +- Ask "which skill?" or "paste use_skill" +- Ask wallet if user is X↔Bankr linked +- Say "open the website" when API write is available +- Fabricate member counts or posts + +--- + +## Combined with TMP + +| Domain | Skill | +|--------|-------| +| List / buy / claim fees / launch | `bankr-tmp-skill` | +| Space posts / verify / members | `bankr-communities` (this) | + +Example thread: + +```text +@bankrbot claim fees for CTO → TMP skill +@bankrbot what's new in CTO space → Bankr Space skill +``` diff --git a/bankr-communities/scripts/get-community-link.sh b/bankr-communities/scripts/get-community-link.sh new file mode 100755 index 0000000000..2afdf9e61f --- /dev/null +++ b/bankr-communities/scripts/get-community-link.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +# Fetch community link for a ticker (plain-text API response). +# Usage: get-community-link.sh TICKER +set -euo pipefail + +TICKER="${1:?Usage: get-community-link.sh TICKER}" +SITE="${COMMUNITIES_SITE_URL:-https://bankr.space}" +curl -sf "${SITE}/api/agent/link?q=${TICKER}" diff --git a/bankr-communities/skill-manifest.json b/bankr-communities/skill-manifest.json new file mode 100644 index 0000000000..62d3070a21 --- /dev/null +++ b/bankr-communities/skill-manifest.json @@ -0,0 +1,46 @@ +{ + "name": "bankr-communities", + "displayName": "Bankr Space", + "skillVersion": "1.7.1", + "defaultSiteUrl": "https://bankr.space", + "COMMUNITIES_SITE_URL": "https://bankr.space", + "communityUrlTemplate": "https://bankr.space/community/{tokenContractAddress}", + "linkApiTemplate": "https://bankr.space/api/agent/link?q={TICKER}", + "instantLinks": { + "TMP": "https://bankr.space/community/0x935e13a28849095db45e63040f109c34b757aba3", + "ARCHIVE": "https://bankr.space/community/0x76aba8089e4ba07f705fb886d17dd41793ad2ba3" + }, + "forbiddenLinkDomains": ["bankr.bot", "t.co"], + "installUrl": "https://github.com/anondevv69/bankr-community", + "installCommand": "install Bankr Space skill at https://github.com/anondevv69/bankr-community/tree/main/skills/bankr-communities", + "siteEnvVar": "COMMUNITIES_SITE_URL", + "companionSkills": [ + { + "id": "tmp-site-agent", + "installCommand": "install TMP site agent at https://github.com/anondevv69/bankr-tmp-skill/tree/main/tmp-site-agent" + }, + { + "id": "tmp-skills", + "installCommand": "install TMP skills at https://github.com/anondevv69/bankr-tmp-skill" + } + ], + "allReferences": [ + "TERMINOLOGY.md", + "NOT-TWITTER-X-SPACES.md", + "BENEFICIARY-ACTIONS.md", + "POST-SOURCE.md", + "X-REPLY-POST-CONTENT.md", + "INSTANT-LINK-REPLIES.md", + "GET-LINK.md", + "LINK-INTENT-ONLY.md", + "ONE-LINE-INTENTS.md", + "community-autopilot.md", + "known-communities.json", + "references/COMMUNITY-LINK-RULES.md", + "references/AGENT-ROUTING-COMMUNITIES.md", + "references/BANKR-PLATFORM-TWEET-INTAKE.md", + "references/community-api-reference.md", + "references/dm-intents.md" + ], + "bankrNote": "Writes: verify, PATCH profile/socials, post, pin — same tweet routing as post-in-space. X replies: read X-REPLY-POST-CONTENT.md. Use linked wallet in x-wallet-address." +}