plugin-syndicate 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  The elizaOS adapter for **The Syndicate** — a deterministic, turn-based
4
4
  crime-city strategy game where the loot is **real trading cards priced by a
5
- live on-chain TCG oracle**. Humans and agents share one world and one
6
- leaderboard.
5
+ live on-chain TCG oracle**. Each syndicate runs its own city; humans and
6
+ agents compete on one shared leaderboard.
7
7
 
8
8
  The game itself is agent-agnostic: **any** agent can play it over the public
9
9
  HTTP API (rules: [SKILL.md](https://play.the-undesirables.com/SKILL.md)) or
@@ -57,6 +57,21 @@ per day. Self verbs (`heal`, `pray`, `lay_low`, `retain`, `injunction`,
57
57
  Set `SYNDICATE_SESSION_ID` in your character settings to resume a specific
58
58
  session (games expire after 7 idle days server-side).
59
59
 
60
+ ## Three real-world feeds, one game
61
+
62
+ - **Card prices** — loot is real cards at live oracle prices; your stash
63
+ re-prices daily. Hold the risers, fence the dippers.
64
+ - **Chicago weather** — the REAL O'Hare observation shapes each day (rain
65
+ favors laying low, heatwaves pay extortion premiums) and the Weather Book
66
+ takes tickets on tomorrow's sky.
67
+ - **MLB stat lines** — the Sports Book sets player props from our
68
+ on-chain-committed daily panel and settles them on the player's next real
69
+ game, with a public Merkle proof cited on every settled ticket.
70
+
71
+ All bets are **in-game capital only** — pretend money, real data. It is a
72
+ practice range for pricing real-world uncertainty with zero real-world
73
+ downside.
74
+
60
75
  ## The one trap worth knowing
61
76
 
62
77
  `beatable: "solo"` assumes your **strongest** member leads the attack — the
package/dist/index.d.ts CHANGED
@@ -5,7 +5,8 @@ import { Plugin } from '@elizaos/core';
5
5
  * ====================================
6
6
  * Lets any elizaOS agent run a crime family in The Syndicate: a deterministic,
7
7
  * turn-based 80×80 city where the loot is REAL trading cards priced by a live
8
- * on-chain TCG oracle. Humans and agents share one world and one leaderboard.
8
+ * on-chain TCG oracle. Each syndicate runs its OWN city; humans and agents
9
+ * compete on one shared leaderboard.
9
10
  *
10
11
  * The game is server-authoritative — this plugin submits order INTENTS to the
11
12
  * public API and narrates what the engine resolved. There is no client-side
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  var GAME_API = "https://play.the-undesirables.com/api/game";
3
3
  var SCORES_API = "https://play.the-undesirables.com/api/scores";
4
4
  var SKILL_URL = "https://play.the-undesirables.com/SKILL.md";
5
- var PLUGIN_VERSION = "0.1.1";
5
+ var PLUGIN_VERSION = "0.2.0";
6
6
  var FETCH_TIMEOUT_MS = 15e3;
7
7
  var sessions = /* @__PURE__ */ new Map();
8
8
  var lastViews = /* @__PURE__ */ new Map();
@@ -62,8 +62,16 @@ function summarizeView(v) {
62
62
  const stash = v.stash || {};
63
63
  const targets = Array.isArray(v.targets) ? v.targets : [];
64
64
  const beatable = targets.filter((t) => t.beatable !== "no").slice(0, 8);
65
+ const weather = v.weather;
66
+ const contract = v.contract;
67
+ const wBet = v.weatherBet;
68
+ const sBet = v.sportsBet;
65
69
  const lines = [
66
70
  `Day ${v.day} \u2014 capital $${v.capital}, heat ${v.heat}, wanted ${v.wantedLevel}`,
71
+ ...weather ? [`Chicago weather (REAL, shifts today's odds): ${weather.condition}, ${weather.tempF}\xB0F \u2014 ${weather.kind}`] : [],
72
+ ...contract ? [`Commission contract: ${contract.desc}`] : [],
73
+ ...wBet ? [`Open weather ticket: $${wBet.stake} on ${wBet.on}`] : [],
74
+ ...sBet ? [`Open sports ticket: $${sBet.stake} on ${sBet.playerName} (${sBet.prop})`] : [],
67
75
  `Territory: ${territory.ownedTiles}/${territory.tilesToWin} tiles toward the Kingpin win`,
68
76
  `Stash: ${stash.cards} card(s), fence value $${stash.fenceValue}`,
69
77
  `Crew: ${crew.map((c) => `${c.name} (hp ${c.hp}${c.unavailable ? `, ${c.unavailable}` : ""})`).join(" \xB7 ")}`,
@@ -149,7 +157,7 @@ var stateAction = {
149
157
  };
150
158
  var moveAction = {
151
159
  name: "SYNDICATE_MOVE",
152
- description: "Submit one day of orders to The Syndicate and get back what the engine resolved. Orders are [{agentId, targetId, actionType, squad?}] \u2014 one per crew member. Self verbs (heal, pray, lay_low, retain, injunction, cook_books, audit, launder) may omit targetId. Check SYNDICATE_STATE first: 'beatable: solo' assumes your STRONGEST member leads.",
160
+ description: "Submit one day of orders to The Syndicate and get back what the engine resolved. Orders are [{agentId, targetId, actionType, squad?}] \u2014 one per crew member. Self verbs (heal, pray, lay_low, retain, injunction, cook_books, audit, launder, weather_bet, sports_bet) may omit targetId. Betting (in-game capital only): {actionType:'weather_bet', on:'rain', stake:500} on tomorrow's REAL Chicago weather; {actionType:'sports_bet', playerId, prop:'hr', stake:500} on a real MLB player's next game \u2014 pick playerId from sportsBook.featured. Check SYNDICATE_STATE first: 'beatable: solo' assumes your STRONGEST member leads.",
153
161
  similes: ["SYNDICATE_ORDERS", "PLAY_TURN", "RUN_THE_DAY"],
154
162
  parameters: [
155
163
  {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * The Syndicate — ElizaOS Plugin v0.1\n * ====================================\n * Lets any elizaOS agent run a crime family in The Syndicate: a deterministic,\n * turn-based 80×80 city where the loot is REAL trading cards priced by a live\n * on-chain TCG oracle. Humans and agents share one world and one leaderboard.\n *\n * The game is server-authoritative — this plugin submits order INTENTS to the\n * public API and narrates what the engine resolved. There is no client-side\n * simulation and nothing to cheat.\n *\n * SYNDICATE_NEW start a game (one session per agent, kept in memory)\n * SYNDICATE_STATE read the current day without spending it\n * SYNDICATE_MOVE submit a day of orders and get the resolved events\n * SYNDICATE_LEADERBOARD the shared human+agent board\n *\n * Rules for models: https://play.the-undesirables.com/SKILL.md\n *\n * @see https://play.the-undesirables.com\n * @see https://github.com/sailorpepe/plugin-syndicate\n */\n\nimport type {\n Plugin,\n Action,\n Provider,\n ProviderResult,\n IAgentRuntime,\n Memory,\n State,\n HandlerCallback,\n ActionExample,\n ActionResult,\n} from \"@elizaos/core\";\n\nconst GAME_API = \"https://play.the-undesirables.com/api/game\";\nconst SCORES_API = \"https://play.the-undesirables.com/api/scores\";\nconst SKILL_URL = \"https://play.the-undesirables.com/SKILL.md\";\nconst PLUGIN_VERSION = \"0.1.1\";\nconst FETCH_TIMEOUT_MS = 15_000;\n\n// ============================================================\n// Session bookkeeping — one live game per agent, in-process.\n// The server holds all state; losing this map only means the\n// agent starts a fresh syndicate (sessions expire in 7 idle\n// days server-side anyway). The last view is cached so the\n// context provider can narrate game state with ZERO extra\n// API calls.\n// ============================================================\n\nconst sessions = new Map<string, string>(); // agentId -> sessionId\nconst lastViews = new Map<string, Record<string, unknown>>(); // agentId -> last view\n\nfunction sessionFor(runtime: IAgentRuntime): string | undefined {\n const configured = runtime.getSetting?.(\"SYNDICATE_SESSION_ID\");\n if (configured && typeof configured === \"string\") return configured;\n return sessions.get(String(runtime.agentId));\n}\n\n/** Marks errors the agent can act on (start a new game, wait out the limit). */\nclass GameError extends Error {\n constructor(message: string, readonly expired = false) { super(message); }\n}\n\nfunction toGameError(status: number, serverMsg: string): GameError {\n if (status === 404) return new GameError(\"Session unknown or expired (games expire after 7 idle days).\", true);\n if (status === 429) return new GameError(\"The city is rate-limited (30 calls/min/IP). Wait a minute, then try again.\");\n if (status === 409) return new GameError(serverMsg || \"Game over — start a new syndicate with SYNDICATE_NEW.\");\n return new GameError(serverMsg || `HTTP ${status}`);\n}\n\nasync function api(body: Record<string, unknown>): Promise<Record<string, unknown>> {\n const res = await fetch(GAME_API, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),\n });\n const data = (await res.json().catch(() => ({}))) as Record<string, unknown>;\n if (!res.ok) throw toGameError(res.status, String((data as { error?: string }).error || \"\"));\n return data;\n}\n\nasync function apiView(sessionId: string): Promise<Record<string, unknown>> {\n const res = await fetch(`${GAME_API}?id=${encodeURIComponent(sessionId)}`, {\n signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),\n });\n const data = (await res.json().catch(() => ({}))) as Record<string, unknown>;\n if (!res.ok) throw toGameError(res.status, String((data as { error?: string }).error || \"\"));\n return data;\n}\n\n/** On session expiry, forget it so validate() steers the agent to SYNDICATE_NEW. */\nfunction handleGameError(runtime: IAgentRuntime, e: unknown): string {\n if (e instanceof GameError && e.expired) {\n sessions.delete(String(runtime.agentId));\n lastViews.delete(String(runtime.agentId));\n return `${e.message} Start fresh with SYNDICATE_NEW.`;\n }\n if (e instanceof Error && e.name === \"TimeoutError\") {\n return \"The game server did not answer within 15s — it may be waking up. Try again shortly.\";\n }\n return e instanceof Error ? e.message : String(e);\n}\n\n// Compact narration so the model sees the day without drowning in JSON.\nfunction summarizeView(v: Record<string, unknown>): string {\n const events = Array.isArray(v.events) ? (v.events as string[]).slice(0, 12) : [];\n const crew = Array.isArray(v.crew) ? (v.crew as Record<string, unknown>[]) : [];\n const power = (v.power || {}) as Record<string, unknown>;\n const territory = (v.territory || {}) as Record<string, unknown>;\n const stash = (v.stash || {}) as Record<string, unknown>;\n const targets = Array.isArray(v.targets) ? (v.targets as Record<string, unknown>[]) : [];\n const beatable = targets.filter((t) => t.beatable !== \"no\").slice(0, 8);\n const lines = [\n `Day ${v.day} — capital $${v.capital}, heat ${v.heat}, wanted ${v.wantedLevel}`,\n `Territory: ${territory.ownedTiles}/${territory.tilesToWin} tiles toward the Kingpin win`,\n `Stash: ${stash.cards} card(s), fence value $${stash.fenceValue}`,\n `Crew: ${crew.map((c) => `${c.name} (hp ${c.hp}${(c as { unavailable?: string }).unavailable ? `, ${(c as { unavailable?: string }).unavailable}` : \"\"})`).join(\" · \")}`,\n `Power: best solo ${power.bestSolo} (${power.bestSoloAgentName}), full squad ${power.fullSquad}`,\n beatable.length\n ? `Beatable now: ${beatable.map((t) => `#${t.tileId} ${t.type} vault $${t.vault} (${t.beatable})`).join(\", \")}`\n : `Nothing is beatable right now — hire muscle or squad up.`,\n ];\n if (events.length) lines.push(\"\", \"What happened:\", ...events.map((e) => ` ${e}`));\n if (v.gameOver) lines.push(\"\", \"GAME OVER — start a new syndicate with SYNDICATE_NEW.\");\n if (v.sessionId) lines.push(\"\", `(session ${v.sessionId} — set SYNDICATE_SESSION_ID to resume it after a restart)`);\n return lines.join(\"\\n\");\n}\n\nfunction remember(runtime: IAgentRuntime, view: Record<string, unknown>): void {\n lastViews.set(String(runtime.agentId), view);\n}\n\n// ============================================================\n// Actions\n// ============================================================\n\nconst newGameAction: Action = {\n name: \"SYNDICATE_NEW\",\n description:\n \"Start a new game of The Syndicate. Creates a fresh crime family in a deterministic 80×80 city. One session per agent; the old session is abandoned.\",\n similes: [\"START_SYNDICATE\", \"NEW_CRIME_FAMILY\", \"PLAY_SYNDICATE\"],\n parameters: [\n {\n name: \"syndicate_name\",\n description: \"Name for your crime family (max 32 chars)\",\n required: false,\n schema: { type: \"string\" },\n },\n ],\n examples: [\n [\n { name: \"{{user1}}\", content: { text: \"Start a syndicate called The Night Owls\" } } as ActionExample,\n { name: \"{{agentName}}\", content: { text: \"Founding The Night Owls...\", action: \"SYNDICATE_NEW\" } } as ActionExample,\n ],\n ],\n validate: async () => true,\n handler: async (\n runtime: IAgentRuntime,\n message: Memory,\n _state?: State,\n options?: Record<string, unknown>,\n callback?: HandlerCallback\n ): Promise<ActionResult | undefined> => {\n const name =\n (options?.syndicate_name as string) ||\n message.content.text?.match(/called\\s+(.{2,32}?)(?:\\.|$)/i)?.[1] ||\n `${runtime.character?.name || \"Agent\"} Syndicate`;\n try {\n const view = await api({ action: \"new\", name: name.slice(0, 32), model: `elizaos/${runtime.character?.name || \"agent\"}` });\n sessions.set(String(runtime.agentId), String(view.sessionId));\n remember(runtime, view);\n const text = `New syndicate founded. Read the rules once: ${SKILL_URL}\\n\\n${summarizeView(view)}`;\n if (callback) await callback({ text });\n return { success: true, text, data: { sessionId: String(view.sessionId), view } };\n } catch (e) {\n const text = `Could not start a game: ${handleGameError(runtime, e)}`;\n if (callback) await callback({ text });\n return { success: false, text };\n }\n },\n};\n\nconst stateAction: Action = {\n name: \"SYNDICATE_STATE\",\n description:\n \"Read the current state of your Syndicate game WITHOUT spending a day: crew, capital, heat, stash value, beatable targets, and progress toward the Kingpin win.\",\n similes: [\"SYNDICATE_STATUS\", \"CHECK_SYNDICATE\", \"GAME_STATE\"],\n parameters: [],\n examples: [\n [\n { name: \"{{user1}}\", content: { text: \"How is the syndicate doing?\" } } as ActionExample,\n { name: \"{{agentName}}\", content: { text: \"Checking the city...\", action: \"SYNDICATE_STATE\" } } as ActionExample,\n ],\n ],\n validate: async (runtime: IAgentRuntime) => sessionFor(runtime) !== undefined,\n handler: async (\n runtime: IAgentRuntime,\n _message: Memory,\n _state?: State,\n _options?: Record<string, unknown>,\n callback?: HandlerCallback\n ): Promise<ActionResult | undefined> => {\n const sessionId = sessionFor(runtime);\n if (!sessionId) {\n const text = \"No game running — use SYNDICATE_NEW to found a syndicate.\";\n if (callback) await callback({ text });\n return { success: false, text };\n }\n try {\n const view = await apiView(sessionId);\n remember(runtime, view);\n const text = summarizeView(view);\n if (callback) await callback({ text });\n return { success: true, text, data: { view } };\n } catch (e) {\n const text = `Could not read the game: ${handleGameError(runtime, e)}`;\n if (callback) await callback({ text });\n return { success: false, text };\n }\n },\n};\n\nconst moveAction: Action = {\n name: \"SYNDICATE_MOVE\",\n description:\n \"Submit one day of orders to The Syndicate and get back what the engine resolved. Orders are [{agentId, targetId, actionType, squad?}] — one per crew member. Self verbs (heal, pray, lay_low, retain, injunction, cook_books, audit, launder) may omit targetId. Check SYNDICATE_STATE first: 'beatable: solo' assumes your STRONGEST member leads.\",\n similes: [\"SYNDICATE_ORDERS\", \"PLAY_TURN\", \"RUN_THE_DAY\"],\n parameters: [\n {\n name: \"orders\",\n description:\n 'JSON array of orders, e.g. [{\"agentId\":123,\"targetId\":612,\"actionType\":\"raid\",\"squad\":[124,156]}]. An empty array passes the day (the world still moves).',\n required: true,\n schema: { type: \"string\" },\n },\n ],\n examples: [\n [\n { name: \"{{user1}}\", content: { text: \"Send Rogue to raid the accountant at tile 612\" } } as ActionExample,\n { name: \"{{agentName}}\", content: { text: \"Running the day...\", action: \"SYNDICATE_MOVE\" } } as ActionExample,\n ],\n ],\n validate: async (runtime: IAgentRuntime) => sessionFor(runtime) !== undefined,\n handler: async (\n runtime: IAgentRuntime,\n message: Memory,\n _state?: State,\n options?: Record<string, unknown>,\n callback?: HandlerCallback\n ): Promise<ActionResult | undefined> => {\n const sessionId = sessionFor(runtime);\n if (!sessionId) {\n const text = \"No game running — use SYNDICATE_NEW to found a syndicate.\";\n if (callback) await callback({ text });\n return { success: false, text };\n }\n let orders: unknown = [];\n const raw = (options?.orders as string) || message.content.text?.match(/\\[[\\s\\S]*\\]/)?.[0] || \"[]\";\n try {\n orders = typeof raw === \"string\" ? JSON.parse(raw) : raw;\n if (!Array.isArray(orders)) throw new Error(\"orders must be a JSON array\");\n } catch (e) {\n const text = `Could not parse orders (${e instanceof Error ? e.message : String(e)}). Expected: [{\"agentId\":ID,\"targetId\":TILE,\"actionType\":\"VERB\"}]`;\n if (callback) await callback({ text });\n return { success: false, text };\n }\n try {\n const view = await api({ action: \"orders\", sessionId, orders });\n remember(runtime, view);\n const text = summarizeView(view);\n if (callback) await callback({ text });\n return { success: true, text, data: { view } };\n } catch (e) {\n const text = `The engine rejected the orders: ${handleGameError(runtime, e)}`;\n if (callback) await callback({ text });\n return { success: false, text };\n }\n },\n};\n\nconst leaderboardAction: Action = {\n name: \"SYNDICATE_LEADERBOARD\",\n description:\n \"Read The Syndicate's shared leaderboard — humans and agents on one board, scored by capital, with agent entries flagged by model.\",\n similes: [\"SYNDICATE_SCORES\", \"TOP_SYNDICATES\", \"CRIME_LEADERBOARD\"],\n parameters: [],\n examples: [\n [\n { name: \"{{user1}}\", content: { text: \"Who runs the city?\" } } as ActionExample,\n { name: \"{{agentName}}\", content: { text: \"Pulling the board...\", action: \"SYNDICATE_LEADERBOARD\" } } as ActionExample,\n ],\n ],\n validate: async () => true,\n handler: async (\n _runtime: IAgentRuntime,\n _message: Memory,\n _state?: State,\n _options?: Record<string, unknown>,\n callback?: HandlerCallback\n ): Promise<ActionResult | undefined> => {\n try {\n const res = await fetch(SCORES_API, { signal: AbortSignal.timeout(FETCH_TIMEOUT_MS) });\n const data = (await res.json()) as { scores?: { syndicate: string; headline: string; day: number; value: number; agent?: boolean; model?: string }[] };\n const rows = (data.scores || []).slice(0, 10);\n const text = rows.length\n ? rows\n .map(\n (s, i) =>\n `${i + 1}. ${s.syndicate} — $${s.value.toLocaleString()} (day ${s.day}) ${s.agent ? `[agent: ${s.model || \"unknown\"}]` : \"[human]\"} — ${s.headline}`\n )\n .join(\"\\n\")\n : \"The board is empty. The city is up for grabs.\";\n if (callback) await callback({ text });\n return { success: true, text, data: { scores: rows } };\n } catch (e) {\n const text = `Could not reach the leaderboard: ${e instanceof Error ? e.message : String(e)}`;\n if (callback) await callback({ text });\n return { success: false, text };\n }\n },\n};\n\n// ============================================================\n// Provider — narrates the cached game state into context on\n// every message, with ZERO extra API calls. The cache is only\n// written by the actions, so this can never spam the server.\n// ============================================================\n\nconst syndicateProvider: Provider = {\n name: \"syndicate-game-state\",\n description: \"Current state of the agent's Syndicate game (cached from the last action; no network calls)\",\n get: async (runtime: IAgentRuntime, _message: Memory, _state?: State): Promise<ProviderResult> => {\n const view = lastViews.get(String(runtime.agentId));\n if (!view || !sessionFor(runtime)) return { text: \"\" };\n const territory = (view.territory || {}) as Record<string, unknown>;\n const stash = (view.stash || {}) as Record<string, unknown>;\n return {\n text: `[The Syndicate — day ${view.day}: capital $${view.capital}, heat ${view.heat}, ` +\n `${territory.ownedTiles}/${territory.tilesToWin} tiles, stash $${stash.fenceValue}. ` +\n `Use SYNDICATE_STATE for detail, SYNDICATE_MOVE to play the day.]`,\n data: { view },\n };\n },\n};\n\n// ============================================================\n// Plugin\n// ============================================================\n\nexport const syndicatePlugin: Plugin = {\n name: \"plugin-syndicate\",\n description: `The Syndicate v${PLUGIN_VERSION} — agent-playable crime-city strategy with oracle-priced loot. Rules: ${SKILL_URL}`,\n actions: [newGameAction, stateAction, moveAction, leaderboardAction],\n providers: [syndicateProvider],\n evaluators: [],\n};\n\nexport default syndicatePlugin;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * The Syndicate — ElizaOS Plugin v0.1\n * ====================================\n * Lets any elizaOS agent run a crime family in The Syndicate: a deterministic,\n * turn-based 80×80 city where the loot is REAL trading cards priced by a live\n * on-chain TCG oracle. Each syndicate runs its OWN city; humans and agents\n * compete on one shared leaderboard.\n *\n * The game is server-authoritative — this plugin submits order INTENTS to the\n * public API and narrates what the engine resolved. There is no client-side\n * simulation and nothing to cheat.\n *\n * SYNDICATE_NEW start a game (one session per agent, kept in memory)\n * SYNDICATE_STATE read the current day without spending it\n * SYNDICATE_MOVE submit a day of orders and get the resolved events\n * SYNDICATE_LEADERBOARD the shared human+agent board\n *\n * Rules for models: https://play.the-undesirables.com/SKILL.md\n *\n * @see https://play.the-undesirables.com\n * @see https://github.com/sailorpepe/plugin-syndicate\n */\n\nimport type {\n Plugin,\n Action,\n Provider,\n ProviderResult,\n IAgentRuntime,\n Memory,\n State,\n HandlerCallback,\n ActionExample,\n ActionResult,\n} from \"@elizaos/core\";\n\nconst GAME_API = \"https://play.the-undesirables.com/api/game\";\nconst SCORES_API = \"https://play.the-undesirables.com/api/scores\";\nconst SKILL_URL = \"https://play.the-undesirables.com/SKILL.md\";\nconst PLUGIN_VERSION = \"0.2.0\";\nconst FETCH_TIMEOUT_MS = 15_000;\n\n// ============================================================\n// Session bookkeeping — one live game per agent, in-process.\n// The server holds all state; losing this map only means the\n// agent starts a fresh syndicate (sessions expire in 7 idle\n// days server-side anyway). The last view is cached so the\n// context provider can narrate game state with ZERO extra\n// API calls.\n// ============================================================\n\nconst sessions = new Map<string, string>(); // agentId -> sessionId\nconst lastViews = new Map<string, Record<string, unknown>>(); // agentId -> last view\n\nfunction sessionFor(runtime: IAgentRuntime): string | undefined {\n const configured = runtime.getSetting?.(\"SYNDICATE_SESSION_ID\");\n if (configured && typeof configured === \"string\") return configured;\n return sessions.get(String(runtime.agentId));\n}\n\n/** Marks errors the agent can act on (start a new game, wait out the limit). */\nclass GameError extends Error {\n constructor(message: string, readonly expired = false) { super(message); }\n}\n\nfunction toGameError(status: number, serverMsg: string): GameError {\n if (status === 404) return new GameError(\"Session unknown or expired (games expire after 7 idle days).\", true);\n if (status === 429) return new GameError(\"The city is rate-limited (30 calls/min/IP). Wait a minute, then try again.\");\n if (status === 409) return new GameError(serverMsg || \"Game over — start a new syndicate with SYNDICATE_NEW.\");\n return new GameError(serverMsg || `HTTP ${status}`);\n}\n\nasync function api(body: Record<string, unknown>): Promise<Record<string, unknown>> {\n const res = await fetch(GAME_API, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),\n });\n const data = (await res.json().catch(() => ({}))) as Record<string, unknown>;\n if (!res.ok) throw toGameError(res.status, String((data as { error?: string }).error || \"\"));\n return data;\n}\n\nasync function apiView(sessionId: string): Promise<Record<string, unknown>> {\n const res = await fetch(`${GAME_API}?id=${encodeURIComponent(sessionId)}`, {\n signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),\n });\n const data = (await res.json().catch(() => ({}))) as Record<string, unknown>;\n if (!res.ok) throw toGameError(res.status, String((data as { error?: string }).error || \"\"));\n return data;\n}\n\n/** On session expiry, forget it so validate() steers the agent to SYNDICATE_NEW. */\nfunction handleGameError(runtime: IAgentRuntime, e: unknown): string {\n if (e instanceof GameError && e.expired) {\n sessions.delete(String(runtime.agentId));\n lastViews.delete(String(runtime.agentId));\n return `${e.message} Start fresh with SYNDICATE_NEW.`;\n }\n if (e instanceof Error && e.name === \"TimeoutError\") {\n return \"The game server did not answer within 15s — it may be waking up. Try again shortly.\";\n }\n return e instanceof Error ? e.message : String(e);\n}\n\n// Compact narration so the model sees the day without drowning in JSON.\nfunction summarizeView(v: Record<string, unknown>): string {\n const events = Array.isArray(v.events) ? (v.events as string[]).slice(0, 12) : [];\n const crew = Array.isArray(v.crew) ? (v.crew as Record<string, unknown>[]) : [];\n const power = (v.power || {}) as Record<string, unknown>;\n const territory = (v.territory || {}) as Record<string, unknown>;\n const stash = (v.stash || {}) as Record<string, unknown>;\n const targets = Array.isArray(v.targets) ? (v.targets as Record<string, unknown>[]) : [];\n const beatable = targets.filter((t) => t.beatable !== \"no\").slice(0, 8);\n const weather = v.weather as Record<string, unknown> | undefined;\n const contract = v.contract as Record<string, unknown> | undefined;\n const wBet = v.weatherBet as Record<string, unknown> | undefined;\n const sBet = v.sportsBet as Record<string, unknown> | undefined;\n const lines = [\n `Day ${v.day} — capital $${v.capital}, heat ${v.heat}, wanted ${v.wantedLevel}`,\n ...(weather ? [`Chicago weather (REAL, shifts today's odds): ${weather.condition}, ${weather.tempF}°F — ${weather.kind}`] : []),\n ...(contract ? [`Commission contract: ${(contract as { desc?: string }).desc}`] : []),\n ...(wBet ? [`Open weather ticket: $${wBet.stake} on ${wBet.on}`] : []),\n ...(sBet ? [`Open sports ticket: $${sBet.stake} on ${sBet.playerName} (${sBet.prop})`] : []),\n `Territory: ${territory.ownedTiles}/${territory.tilesToWin} tiles toward the Kingpin win`,\n `Stash: ${stash.cards} card(s), fence value $${stash.fenceValue}`,\n `Crew: ${crew.map((c) => `${c.name} (hp ${c.hp}${(c as { unavailable?: string }).unavailable ? `, ${(c as { unavailable?: string }).unavailable}` : \"\"})`).join(\" · \")}`,\n `Power: best solo ${power.bestSolo} (${power.bestSoloAgentName}), full squad ${power.fullSquad}`,\n beatable.length\n ? `Beatable now: ${beatable.map((t) => `#${t.tileId} ${t.type} vault $${t.vault} (${t.beatable})`).join(\", \")}`\n : `Nothing is beatable right now — hire muscle or squad up.`,\n ];\n if (events.length) lines.push(\"\", \"What happened:\", ...events.map((e) => ` ${e}`));\n if (v.gameOver) lines.push(\"\", \"GAME OVER — start a new syndicate with SYNDICATE_NEW.\");\n if (v.sessionId) lines.push(\"\", `(session ${v.sessionId} — set SYNDICATE_SESSION_ID to resume it after a restart)`);\n return lines.join(\"\\n\");\n}\n\nfunction remember(runtime: IAgentRuntime, view: Record<string, unknown>): void {\n lastViews.set(String(runtime.agentId), view);\n}\n\n// ============================================================\n// Actions\n// ============================================================\n\nconst newGameAction: Action = {\n name: \"SYNDICATE_NEW\",\n description:\n \"Start a new game of The Syndicate. Creates a fresh crime family in a deterministic 80×80 city. One session per agent; the old session is abandoned.\",\n similes: [\"START_SYNDICATE\", \"NEW_CRIME_FAMILY\", \"PLAY_SYNDICATE\"],\n parameters: [\n {\n name: \"syndicate_name\",\n description: \"Name for your crime family (max 32 chars)\",\n required: false,\n schema: { type: \"string\" },\n },\n ],\n examples: [\n [\n { name: \"{{user1}}\", content: { text: \"Start a syndicate called The Night Owls\" } } as ActionExample,\n { name: \"{{agentName}}\", content: { text: \"Founding The Night Owls...\", action: \"SYNDICATE_NEW\" } } as ActionExample,\n ],\n ],\n validate: async () => true,\n handler: async (\n runtime: IAgentRuntime,\n message: Memory,\n _state?: State,\n options?: Record<string, unknown>,\n callback?: HandlerCallback\n ): Promise<ActionResult | undefined> => {\n const name =\n (options?.syndicate_name as string) ||\n message.content.text?.match(/called\\s+(.{2,32}?)(?:\\.|$)/i)?.[1] ||\n `${runtime.character?.name || \"Agent\"} Syndicate`;\n try {\n const view = await api({ action: \"new\", name: name.slice(0, 32), model: `elizaos/${runtime.character?.name || \"agent\"}` });\n sessions.set(String(runtime.agentId), String(view.sessionId));\n remember(runtime, view);\n const text = `New syndicate founded. Read the rules once: ${SKILL_URL}\\n\\n${summarizeView(view)}`;\n if (callback) await callback({ text });\n return { success: true, text, data: { sessionId: String(view.sessionId), view } };\n } catch (e) {\n const text = `Could not start a game: ${handleGameError(runtime, e)}`;\n if (callback) await callback({ text });\n return { success: false, text };\n }\n },\n};\n\nconst stateAction: Action = {\n name: \"SYNDICATE_STATE\",\n description:\n \"Read the current state of your Syndicate game WITHOUT spending a day: crew, capital, heat, stash value, beatable targets, and progress toward the Kingpin win.\",\n similes: [\"SYNDICATE_STATUS\", \"CHECK_SYNDICATE\", \"GAME_STATE\"],\n parameters: [],\n examples: [\n [\n { name: \"{{user1}}\", content: { text: \"How is the syndicate doing?\" } } as ActionExample,\n { name: \"{{agentName}}\", content: { text: \"Checking the city...\", action: \"SYNDICATE_STATE\" } } as ActionExample,\n ],\n ],\n validate: async (runtime: IAgentRuntime) => sessionFor(runtime) !== undefined,\n handler: async (\n runtime: IAgentRuntime,\n _message: Memory,\n _state?: State,\n _options?: Record<string, unknown>,\n callback?: HandlerCallback\n ): Promise<ActionResult | undefined> => {\n const sessionId = sessionFor(runtime);\n if (!sessionId) {\n const text = \"No game running — use SYNDICATE_NEW to found a syndicate.\";\n if (callback) await callback({ text });\n return { success: false, text };\n }\n try {\n const view = await apiView(sessionId);\n remember(runtime, view);\n const text = summarizeView(view);\n if (callback) await callback({ text });\n return { success: true, text, data: { view } };\n } catch (e) {\n const text = `Could not read the game: ${handleGameError(runtime, e)}`;\n if (callback) await callback({ text });\n return { success: false, text };\n }\n },\n};\n\nconst moveAction: Action = {\n name: \"SYNDICATE_MOVE\",\n description:\n \"Submit one day of orders to The Syndicate and get back what the engine resolved. Orders are [{agentId, targetId, actionType, squad?}] — one per crew member. Self verbs (heal, pray, lay_low, retain, injunction, cook_books, audit, launder, weather_bet, sports_bet) may omit targetId. Betting (in-game capital only): {actionType:'weather_bet', on:'rain', stake:500} on tomorrow's REAL Chicago weather; {actionType:'sports_bet', playerId, prop:'hr', stake:500} on a real MLB player's next game — pick playerId from sportsBook.featured. Check SYNDICATE_STATE first: 'beatable: solo' assumes your STRONGEST member leads.\",\n similes: [\"SYNDICATE_ORDERS\", \"PLAY_TURN\", \"RUN_THE_DAY\"],\n parameters: [\n {\n name: \"orders\",\n description:\n 'JSON array of orders, e.g. [{\"agentId\":123,\"targetId\":612,\"actionType\":\"raid\",\"squad\":[124,156]}]. An empty array passes the day (the world still moves).',\n required: true,\n schema: { type: \"string\" },\n },\n ],\n examples: [\n [\n { name: \"{{user1}}\", content: { text: \"Send Rogue to raid the accountant at tile 612\" } } as ActionExample,\n { name: \"{{agentName}}\", content: { text: \"Running the day...\", action: \"SYNDICATE_MOVE\" } } as ActionExample,\n ],\n ],\n validate: async (runtime: IAgentRuntime) => sessionFor(runtime) !== undefined,\n handler: async (\n runtime: IAgentRuntime,\n message: Memory,\n _state?: State,\n options?: Record<string, unknown>,\n callback?: HandlerCallback\n ): Promise<ActionResult | undefined> => {\n const sessionId = sessionFor(runtime);\n if (!sessionId) {\n const text = \"No game running — use SYNDICATE_NEW to found a syndicate.\";\n if (callback) await callback({ text });\n return { success: false, text };\n }\n let orders: unknown = [];\n const raw = (options?.orders as string) || message.content.text?.match(/\\[[\\s\\S]*\\]/)?.[0] || \"[]\";\n try {\n orders = typeof raw === \"string\" ? JSON.parse(raw) : raw;\n if (!Array.isArray(orders)) throw new Error(\"orders must be a JSON array\");\n } catch (e) {\n const text = `Could not parse orders (${e instanceof Error ? e.message : String(e)}). Expected: [{\"agentId\":ID,\"targetId\":TILE,\"actionType\":\"VERB\"}]`;\n if (callback) await callback({ text });\n return { success: false, text };\n }\n try {\n const view = await api({ action: \"orders\", sessionId, orders });\n remember(runtime, view);\n const text = summarizeView(view);\n if (callback) await callback({ text });\n return { success: true, text, data: { view } };\n } catch (e) {\n const text = `The engine rejected the orders: ${handleGameError(runtime, e)}`;\n if (callback) await callback({ text });\n return { success: false, text };\n }\n },\n};\n\nconst leaderboardAction: Action = {\n name: \"SYNDICATE_LEADERBOARD\",\n description:\n \"Read The Syndicate's shared leaderboard — humans and agents on one board, scored by capital, with agent entries flagged by model.\",\n similes: [\"SYNDICATE_SCORES\", \"TOP_SYNDICATES\", \"CRIME_LEADERBOARD\"],\n parameters: [],\n examples: [\n [\n { name: \"{{user1}}\", content: { text: \"Who runs the city?\" } } as ActionExample,\n { name: \"{{agentName}}\", content: { text: \"Pulling the board...\", action: \"SYNDICATE_LEADERBOARD\" } } as ActionExample,\n ],\n ],\n validate: async () => true,\n handler: async (\n _runtime: IAgentRuntime,\n _message: Memory,\n _state?: State,\n _options?: Record<string, unknown>,\n callback?: HandlerCallback\n ): Promise<ActionResult | undefined> => {\n try {\n const res = await fetch(SCORES_API, { signal: AbortSignal.timeout(FETCH_TIMEOUT_MS) });\n const data = (await res.json()) as { scores?: { syndicate: string; headline: string; day: number; value: number; agent?: boolean; model?: string }[] };\n const rows = (data.scores || []).slice(0, 10);\n const text = rows.length\n ? rows\n .map(\n (s, i) =>\n `${i + 1}. ${s.syndicate} — $${s.value.toLocaleString()} (day ${s.day}) ${s.agent ? `[agent: ${s.model || \"unknown\"}]` : \"[human]\"} — ${s.headline}`\n )\n .join(\"\\n\")\n : \"The board is empty. The city is up for grabs.\";\n if (callback) await callback({ text });\n return { success: true, text, data: { scores: rows } };\n } catch (e) {\n const text = `Could not reach the leaderboard: ${e instanceof Error ? e.message : String(e)}`;\n if (callback) await callback({ text });\n return { success: false, text };\n }\n },\n};\n\n// ============================================================\n// Provider — narrates the cached game state into context on\n// every message, with ZERO extra API calls. The cache is only\n// written by the actions, so this can never spam the server.\n// ============================================================\n\nconst syndicateProvider: Provider = {\n name: \"syndicate-game-state\",\n description: \"Current state of the agent's Syndicate game (cached from the last action; no network calls)\",\n get: async (runtime: IAgentRuntime, _message: Memory, _state?: State): Promise<ProviderResult> => {\n const view = lastViews.get(String(runtime.agentId));\n if (!view || !sessionFor(runtime)) return { text: \"\" };\n const territory = (view.territory || {}) as Record<string, unknown>;\n const stash = (view.stash || {}) as Record<string, unknown>;\n return {\n text: `[The Syndicate — day ${view.day}: capital $${view.capital}, heat ${view.heat}, ` +\n `${territory.ownedTiles}/${territory.tilesToWin} tiles, stash $${stash.fenceValue}. ` +\n `Use SYNDICATE_STATE for detail, SYNDICATE_MOVE to play the day.]`,\n data: { view },\n };\n },\n};\n\n// ============================================================\n// Plugin\n// ============================================================\n\nexport const syndicatePlugin: Plugin = {\n name: \"plugin-syndicate\",\n description: `The Syndicate v${PLUGIN_VERSION} — agent-playable crime-city strategy with oracle-priced loot. Rules: ${SKILL_URL}`,\n actions: [newGameAction, stateAction, moveAction, leaderboardAction],\n providers: [syndicateProvider],\n evaluators: [],\n};\n\nexport default syndicatePlugin;\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "plugin-syndicate",
3
- "version": "0.1.1",
4
- "description": "Play The Syndicate from any elizaOS agent — a deterministic, turn-based crime-city game where the loot is real trading cards priced by a live on-chain TCG oracle. Humans and agents share one world and one leaderboard.",
3
+ "version": "0.2.0",
4
+ "description": "Play The Syndicate from any elizaOS agent — a deterministic, turn-based crime-city game where the loot is real trading cards priced by a live on-chain TCG oracle. Each syndicate runs its own city; humans and agents compete on one shared leaderboard.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",