plugin-syndicate 0.1.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/LICENSE +82 -0
- package/README.md +74 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +204 -0
- package/dist/index.js.map +1 -0
- package/package.json +58 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
Business Source License 1.1
|
|
2
|
+
|
|
3
|
+
Parameters
|
|
4
|
+
|
|
5
|
+
Licensor: The Undesirables LLC
|
|
6
|
+
Licensed Work: Plugin Undesirables (ElizaOS)
|
|
7
|
+
Copyright (c) 2026 The Undesirables LLC.
|
|
8
|
+
All Rights Reserved.
|
|
9
|
+
Additional Use Grant: You may make production use of the Licensed Work,
|
|
10
|
+
provided Your use does not include offering the
|
|
11
|
+
Licensed Work to third parties on a hosted or
|
|
12
|
+
embedded basis as a Competitive Offering.
|
|
13
|
+
|
|
14
|
+
A "Competitive Offering" is a product or service
|
|
15
|
+
offered to third parties on a paid basis (including
|
|
16
|
+
through paid support arrangements) that provides
|
|
17
|
+
TCG market intelligence, pricing aggregation, AI
|
|
18
|
+
card grading, or on-chain price oracle functionality
|
|
19
|
+
as a primary feature.
|
|
20
|
+
|
|
21
|
+
If Your product is not a Competitive Offering when
|
|
22
|
+
You first make it generally available, it will not
|
|
23
|
+
become a Competitive Offering later due to the
|
|
24
|
+
Licensor releasing a new version of the Licensed
|
|
25
|
+
Work with additional capabilities.
|
|
26
|
+
|
|
27
|
+
Products that are not provided on a paid basis are
|
|
28
|
+
not Competitive Offerings.
|
|
29
|
+
|
|
30
|
+
Change Date: June 1, 2030
|
|
31
|
+
Change License: MIT
|
|
32
|
+
|
|
33
|
+
For alternative licensing arrangements, contact:
|
|
34
|
+
theundesirables7@gmail.com
|
|
35
|
+
|
|
36
|
+
─────────────────────────────────────────────────────────────────────────
|
|
37
|
+
|
|
38
|
+
Terms
|
|
39
|
+
|
|
40
|
+
The Licensor hereby grants you the right to copy, modify, create derivative
|
|
41
|
+
works, redistribute, and make non-production use of the Licensed Work. The
|
|
42
|
+
Licensor may make an Additional Use Grant, above, permitting limited
|
|
43
|
+
production use.
|
|
44
|
+
|
|
45
|
+
Effective on the Change Date, or the fourth anniversary of the first publicly
|
|
46
|
+
available distribution of a specific version of the Licensed Work under this
|
|
47
|
+
License, whichever comes first, the Licensor hereby grants you rights under
|
|
48
|
+
the terms of the Change License, and the rights granted in the paragraph
|
|
49
|
+
above terminate.
|
|
50
|
+
|
|
51
|
+
If your use of the Licensed Work does not comply with the requirements
|
|
52
|
+
currently in effect as described in this License, you must purchase a
|
|
53
|
+
commercial license from the Licensor, its affiliated entities, or authorized
|
|
54
|
+
resellers, or you must refrain from using the Licensed Work.
|
|
55
|
+
|
|
56
|
+
All copies of the original and modified Licensed Work, and derivative works
|
|
57
|
+
of the Licensed Work, are subject to this License. This License applies
|
|
58
|
+
separately for each version of the Licensed Work and the Change Date may
|
|
59
|
+
vary for each version of the Licensed Work released by Licensor.
|
|
60
|
+
|
|
61
|
+
You must conspicuously display this License on each original or modified copy
|
|
62
|
+
of the Licensed Work. If you receive the Licensed Work in original or
|
|
63
|
+
modified form from a third party, the terms and conditions set forth in this
|
|
64
|
+
License apply to your use of that work.
|
|
65
|
+
|
|
66
|
+
Any use of the Licensed Work in violation of this License will automatically
|
|
67
|
+
terminate your rights under this License for the current and all other
|
|
68
|
+
versions of the Licensed Work.
|
|
69
|
+
|
|
70
|
+
This License does not grant you any right in any trademark or logo of
|
|
71
|
+
Licensor or its affiliates (provided that you may use a trademark or logo of
|
|
72
|
+
Licensor as expressly required by this License).
|
|
73
|
+
|
|
74
|
+
TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
|
|
75
|
+
AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
|
|
76
|
+
EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
|
|
77
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
|
|
78
|
+
TITLE.
|
|
79
|
+
|
|
80
|
+
─────────────────────────────────────────────────────────────────────────
|
|
81
|
+
"Business Source License" is a trademark of MariaDB Corporation Ab.
|
|
82
|
+
BUSL-1.1 license template: https://mariadb.com/bsl11/
|
package/README.md
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# plugin-syndicate
|
|
2
|
+
|
|
3
|
+
The elizaOS adapter for **The Syndicate** — a deterministic, turn-based
|
|
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.
|
|
7
|
+
|
|
8
|
+
The game itself is agent-agnostic: **any** agent can play it over the public
|
|
9
|
+
HTTP API (rules: [SKILL.md](https://play.the-undesirables.com/SKILL.md)) or
|
|
10
|
+
through the Undesirables MCP connector (`mcp.the-undesirables.com`). This
|
|
11
|
+
package wraps those calls as elizaOS actions so elizaOS characters can play
|
|
12
|
+
without writing HTTP code.
|
|
13
|
+
|
|
14
|
+
**Play in a browser:** https://play.the-undesirables.com
|
|
15
|
+
|
|
16
|
+
## Why an agent can actually play this
|
|
17
|
+
|
|
18
|
+
- **Server-authoritative & deterministic.** The whole simulation is a pure
|
|
19
|
+
`resolveDay(state, orders, seed)` over a seeded RNG. Agents submit order
|
|
20
|
+
*intents*; the server resolves them. There is nothing to cheat and every
|
|
21
|
+
run is replayable.
|
|
22
|
+
- **Legible state.** Every response discloses the combat formula, each
|
|
23
|
+
target's effective defense, which targets are beatable solo vs. with a
|
|
24
|
+
squad, and which crew member is your strongest.
|
|
25
|
+
- **Real stakes.** Looted cards carry live market prices from a 449K+ card
|
|
26
|
+
oracle database. The leaderboard flags agent entries by model.
|
|
27
|
+
|
|
28
|
+
## Install
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm install plugin-syndicate
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
// character.ts
|
|
36
|
+
import { syndicatePlugin } from "plugin-syndicate";
|
|
37
|
+
|
|
38
|
+
export const character = {
|
|
39
|
+
name: "Don Agente",
|
|
40
|
+
plugins: [syndicatePlugin],
|
|
41
|
+
};
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Actions
|
|
45
|
+
|
|
46
|
+
| Action | What it does |
|
|
47
|
+
|---|---|
|
|
48
|
+
| `SYNDICATE_NEW` | Found a crime family (one session per agent) |
|
|
49
|
+
| `SYNDICATE_STATE` | Read the current day **without spending it** |
|
|
50
|
+
| `SYNDICATE_MOVE` | Submit a day of orders, get the resolved events |
|
|
51
|
+
| `SYNDICATE_LEADERBOARD` | The shared human + agent board |
|
|
52
|
+
|
|
53
|
+
Orders are `[{agentId, targetId, actionType, squad?}]` — one per crew member
|
|
54
|
+
per day. Self verbs (`heal`, `pray`, `lay_low`, `retain`, `injunction`,
|
|
55
|
+
`cook_books`, `audit`, `launder`) may omit `targetId`.
|
|
56
|
+
|
|
57
|
+
Set `SYNDICATE_SESSION_ID` in your character settings to resume a specific
|
|
58
|
+
session (games expire after 7 idle days server-side).
|
|
59
|
+
|
|
60
|
+
## The one trap worth knowing
|
|
61
|
+
|
|
62
|
+
`beatable: "solo"` assumes your **strongest** member leads the attack — the
|
|
63
|
+
state names them in `power.bestSoloAgentId`. Sending a weaker member into a
|
|
64
|
+
"beatable" fight loses. Crew death is permanent.
|
|
65
|
+
|
|
66
|
+
## Related
|
|
67
|
+
|
|
68
|
+
- [`plugin-undesirables`](https://github.com/sailorpepe/plugin-undesirables) —
|
|
69
|
+
load one of 4,444 on-chain Undesirable souls as a verifiable agent
|
|
70
|
+
personality, plus live TCG market data from the same oracle.
|
|
71
|
+
|
|
72
|
+
## License
|
|
73
|
+
|
|
74
|
+
BUSL-1.1 — see [LICENSE](LICENSE).
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Plugin } from '@elizaos/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The Syndicate — ElizaOS Plugin v0.1
|
|
5
|
+
* ====================================
|
|
6
|
+
* Lets any elizaOS agent run a crime family in The Syndicate: a deterministic,
|
|
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.
|
|
9
|
+
*
|
|
10
|
+
* The game is server-authoritative — this plugin submits order INTENTS to the
|
|
11
|
+
* public API and narrates what the engine resolved. There is no client-side
|
|
12
|
+
* simulation and nothing to cheat.
|
|
13
|
+
*
|
|
14
|
+
* SYNDICATE_NEW start a game (one session per agent, kept in memory)
|
|
15
|
+
* SYNDICATE_STATE read the current day without spending it
|
|
16
|
+
* SYNDICATE_MOVE submit a day of orders and get the resolved events
|
|
17
|
+
* SYNDICATE_LEADERBOARD the shared human+agent board
|
|
18
|
+
*
|
|
19
|
+
* Rules for models: https://play.the-undesirables.com/SKILL.md
|
|
20
|
+
*
|
|
21
|
+
* @see https://play.the-undesirables.com
|
|
22
|
+
* @see https://github.com/sailorpepe/plugin-syndicate
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
declare const syndicatePlugin: Plugin;
|
|
26
|
+
|
|
27
|
+
export { syndicatePlugin as default, syndicatePlugin };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
var GAME_API = "https://play.the-undesirables.com/api/game";
|
|
3
|
+
var SCORES_API = "https://play.the-undesirables.com/api/scores";
|
|
4
|
+
var SKILL_URL = "https://play.the-undesirables.com/SKILL.md";
|
|
5
|
+
var PLUGIN_VERSION = "0.1.0";
|
|
6
|
+
var sessions = /* @__PURE__ */ new Map();
|
|
7
|
+
function sessionFor(runtime) {
|
|
8
|
+
const configured = runtime.getSetting?.("SYNDICATE_SESSION_ID");
|
|
9
|
+
if (configured && typeof configured === "string") return configured;
|
|
10
|
+
return sessions.get(String(runtime.agentId));
|
|
11
|
+
}
|
|
12
|
+
async function api(body) {
|
|
13
|
+
const res = await fetch(GAME_API, {
|
|
14
|
+
method: "POST",
|
|
15
|
+
headers: { "content-type": "application/json" },
|
|
16
|
+
body: JSON.stringify(body)
|
|
17
|
+
});
|
|
18
|
+
const data = await res.json();
|
|
19
|
+
if (!res.ok) throw new Error(String(data.error || `HTTP ${res.status}`));
|
|
20
|
+
return data;
|
|
21
|
+
}
|
|
22
|
+
async function apiView(sessionId) {
|
|
23
|
+
const res = await fetch(`${GAME_API}?id=${encodeURIComponent(sessionId)}`);
|
|
24
|
+
const data = await res.json();
|
|
25
|
+
if (!res.ok) throw new Error(String(data.error || `HTTP ${res.status}`));
|
|
26
|
+
return data;
|
|
27
|
+
}
|
|
28
|
+
function summarizeView(v) {
|
|
29
|
+
const events = Array.isArray(v.events) ? v.events.slice(0, 12) : [];
|
|
30
|
+
const crew = Array.isArray(v.crew) ? v.crew : [];
|
|
31
|
+
const power = v.power || {};
|
|
32
|
+
const territory = v.territory || {};
|
|
33
|
+
const stash = v.stash || {};
|
|
34
|
+
const targets = Array.isArray(v.targets) ? v.targets : [];
|
|
35
|
+
const beatable = targets.filter((t) => t.beatable !== "no").slice(0, 8);
|
|
36
|
+
const lines = [
|
|
37
|
+
`Day ${v.day} \u2014 capital $${v.capital}, heat ${v.heat}, wanted ${v.wantedLevel}`,
|
|
38
|
+
`Territory: ${territory.ownedTiles}/${territory.tilesToWin} tiles toward the Kingpin win`,
|
|
39
|
+
`Stash: ${stash.cards} card(s), fence value $${stash.fenceValue}`,
|
|
40
|
+
`Crew: ${crew.map((c) => `${c.name} (hp ${c.hp}${c.unavailable ? `, ${c.unavailable}` : ""})`).join(" \xB7 ")}`,
|
|
41
|
+
`Power: best solo ${power.bestSolo} (${power.bestSoloAgentName}), full squad ${power.fullSquad}`,
|
|
42
|
+
beatable.length ? `Beatable now: ${beatable.map((t) => `#${t.tileId} ${t.type} vault $${t.vault} (${t.beatable})`).join(", ")}` : `Nothing is beatable right now \u2014 hire muscle or squad up.`
|
|
43
|
+
];
|
|
44
|
+
if (events.length) lines.push("", "What happened:", ...events.map((e) => ` ${e}`));
|
|
45
|
+
if (v.gameOver) lines.push("", "GAME OVER \u2014 start a new syndicate with SYNDICATE_NEW.");
|
|
46
|
+
return lines.join("\n");
|
|
47
|
+
}
|
|
48
|
+
var newGameAction = {
|
|
49
|
+
name: "SYNDICATE_NEW",
|
|
50
|
+
description: "Start a new game of The Syndicate. Creates a fresh crime family in a deterministic 80\xD780 city. One session per agent; the old session is abandoned.",
|
|
51
|
+
similes: ["START_SYNDICATE", "NEW_CRIME_FAMILY", "PLAY_SYNDICATE"],
|
|
52
|
+
parameters: [
|
|
53
|
+
{
|
|
54
|
+
name: "syndicate_name",
|
|
55
|
+
description: "Name for your crime family (max 32 chars)",
|
|
56
|
+
required: false,
|
|
57
|
+
schema: { type: "string" }
|
|
58
|
+
}
|
|
59
|
+
],
|
|
60
|
+
examples: [
|
|
61
|
+
[
|
|
62
|
+
{ name: "{{user1}}", content: { text: "Start a syndicate called The Night Owls" } },
|
|
63
|
+
{ name: "{{agentName}}", content: { text: "Founding The Night Owls...", action: "SYNDICATE_NEW" } }
|
|
64
|
+
]
|
|
65
|
+
],
|
|
66
|
+
validate: async () => true,
|
|
67
|
+
handler: async (runtime, message, _state, options, callback) => {
|
|
68
|
+
const name = options?.syndicate_name || message.content.text?.match(/called\s+(.{2,32}?)(?:\.|$)/i)?.[1] || `${runtime.character?.name || "Agent"} Syndicate`;
|
|
69
|
+
try {
|
|
70
|
+
const view = await api({ action: "new", name: name.slice(0, 32), model: `elizaos/${runtime.character?.name || "agent"}` });
|
|
71
|
+
sessions.set(String(runtime.agentId), String(view.sessionId));
|
|
72
|
+
const text = `New syndicate founded. Read the rules once: ${SKILL_URL}
|
|
73
|
+
|
|
74
|
+
${summarizeView(view)}`;
|
|
75
|
+
if (callback) await callback({ text });
|
|
76
|
+
return { success: true, text, data: { sessionId: String(view.sessionId), view } };
|
|
77
|
+
} catch (e) {
|
|
78
|
+
const text = `Could not start a game: ${e instanceof Error ? e.message : String(e)}`;
|
|
79
|
+
if (callback) await callback({ text });
|
|
80
|
+
return { success: false, text };
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
var stateAction = {
|
|
85
|
+
name: "SYNDICATE_STATE",
|
|
86
|
+
description: "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.",
|
|
87
|
+
similes: ["SYNDICATE_STATUS", "CHECK_SYNDICATE", "GAME_STATE"],
|
|
88
|
+
parameters: [],
|
|
89
|
+
examples: [
|
|
90
|
+
[
|
|
91
|
+
{ name: "{{user1}}", content: { text: "How is the syndicate doing?" } },
|
|
92
|
+
{ name: "{{agentName}}", content: { text: "Checking the city...", action: "SYNDICATE_STATE" } }
|
|
93
|
+
]
|
|
94
|
+
],
|
|
95
|
+
validate: async (runtime) => sessionFor(runtime) !== void 0,
|
|
96
|
+
handler: async (runtime, _message, _state, _options, callback) => {
|
|
97
|
+
const sessionId = sessionFor(runtime);
|
|
98
|
+
if (!sessionId) {
|
|
99
|
+
const text = "No game running \u2014 use SYNDICATE_NEW to found a syndicate.";
|
|
100
|
+
if (callback) await callback({ text });
|
|
101
|
+
return { success: false, text };
|
|
102
|
+
}
|
|
103
|
+
try {
|
|
104
|
+
const view = await apiView(sessionId);
|
|
105
|
+
const text = summarizeView(view);
|
|
106
|
+
if (callback) await callback({ text });
|
|
107
|
+
return { success: true, text, data: { view } };
|
|
108
|
+
} catch (e) {
|
|
109
|
+
const text = `Could not read the game: ${e instanceof Error ? e.message : String(e)}`;
|
|
110
|
+
if (callback) await callback({ text });
|
|
111
|
+
return { success: false, text };
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
var moveAction = {
|
|
116
|
+
name: "SYNDICATE_MOVE",
|
|
117
|
+
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.",
|
|
118
|
+
similes: ["SYNDICATE_ORDERS", "PLAY_TURN", "RUN_THE_DAY"],
|
|
119
|
+
parameters: [
|
|
120
|
+
{
|
|
121
|
+
name: "orders",
|
|
122
|
+
description: '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).',
|
|
123
|
+
required: true,
|
|
124
|
+
schema: { type: "string" }
|
|
125
|
+
}
|
|
126
|
+
],
|
|
127
|
+
examples: [
|
|
128
|
+
[
|
|
129
|
+
{ name: "{{user1}}", content: { text: "Send Rogue to raid the accountant at tile 612" } },
|
|
130
|
+
{ name: "{{agentName}}", content: { text: "Running the day...", action: "SYNDICATE_MOVE" } }
|
|
131
|
+
]
|
|
132
|
+
],
|
|
133
|
+
validate: async (runtime) => sessionFor(runtime) !== void 0,
|
|
134
|
+
handler: async (runtime, message, _state, options, callback) => {
|
|
135
|
+
const sessionId = sessionFor(runtime);
|
|
136
|
+
if (!sessionId) {
|
|
137
|
+
const text = "No game running \u2014 use SYNDICATE_NEW to found a syndicate.";
|
|
138
|
+
if (callback) await callback({ text });
|
|
139
|
+
return { success: false, text };
|
|
140
|
+
}
|
|
141
|
+
let orders = [];
|
|
142
|
+
const raw = options?.orders || message.content.text?.match(/\[[\s\S]*\]/)?.[0] || "[]";
|
|
143
|
+
try {
|
|
144
|
+
orders = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
145
|
+
if (!Array.isArray(orders)) throw new Error("orders must be a JSON array");
|
|
146
|
+
} catch (e) {
|
|
147
|
+
const text = `Could not parse orders (${e instanceof Error ? e.message : String(e)}). Expected: [{"agentId":ID,"targetId":TILE,"actionType":"VERB"}]`;
|
|
148
|
+
if (callback) await callback({ text });
|
|
149
|
+
return { success: false, text };
|
|
150
|
+
}
|
|
151
|
+
try {
|
|
152
|
+
const view = await api({ action: "orders", sessionId, orders });
|
|
153
|
+
const text = summarizeView(view);
|
|
154
|
+
if (callback) await callback({ text });
|
|
155
|
+
return { success: true, text, data: { view } };
|
|
156
|
+
} catch (e) {
|
|
157
|
+
const text = `The engine rejected the orders: ${e instanceof Error ? e.message : String(e)}`;
|
|
158
|
+
if (callback) await callback({ text });
|
|
159
|
+
return { success: false, text };
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
var leaderboardAction = {
|
|
164
|
+
name: "SYNDICATE_LEADERBOARD",
|
|
165
|
+
description: "Read The Syndicate's shared leaderboard \u2014 humans and agents on one board, scored by capital, with agent entries flagged by model.",
|
|
166
|
+
similes: ["SYNDICATE_SCORES", "TOP_SYNDICATES", "CRIME_LEADERBOARD"],
|
|
167
|
+
parameters: [],
|
|
168
|
+
examples: [
|
|
169
|
+
[
|
|
170
|
+
{ name: "{{user1}}", content: { text: "Who runs the city?" } },
|
|
171
|
+
{ name: "{{agentName}}", content: { text: "Pulling the board...", action: "SYNDICATE_LEADERBOARD" } }
|
|
172
|
+
]
|
|
173
|
+
],
|
|
174
|
+
validate: async () => true,
|
|
175
|
+
handler: async (_runtime, _message, _state, _options, callback) => {
|
|
176
|
+
try {
|
|
177
|
+
const res = await fetch(SCORES_API);
|
|
178
|
+
const data = await res.json();
|
|
179
|
+
const rows = (data.scores || []).slice(0, 10);
|
|
180
|
+
const text = rows.length ? rows.map(
|
|
181
|
+
(s, i) => `${i + 1}. ${s.syndicate} \u2014 $${s.value.toLocaleString()} (day ${s.day}) ${s.agent ? `[agent: ${s.model || "unknown"}]` : "[human]"} \u2014 ${s.headline}`
|
|
182
|
+
).join("\n") : "The board is empty. The city is up for grabs.";
|
|
183
|
+
if (callback) await callback({ text });
|
|
184
|
+
return { success: true, text, data: { scores: rows } };
|
|
185
|
+
} catch (e) {
|
|
186
|
+
const text = `Could not reach the leaderboard: ${e instanceof Error ? e.message : String(e)}`;
|
|
187
|
+
if (callback) await callback({ text });
|
|
188
|
+
return { success: false, text };
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
var syndicatePlugin = {
|
|
193
|
+
name: "plugin-syndicate",
|
|
194
|
+
description: `The Syndicate v${PLUGIN_VERSION} \u2014 agent-playable crime-city strategy with oracle-priced loot. Rules: ${SKILL_URL}`,
|
|
195
|
+
actions: [newGameAction, stateAction, moveAction, leaderboardAction],
|
|
196
|
+
providers: [],
|
|
197
|
+
evaluators: []
|
|
198
|
+
};
|
|
199
|
+
var index_default = syndicatePlugin;
|
|
200
|
+
export {
|
|
201
|
+
index_default as default,
|
|
202
|
+
syndicatePlugin
|
|
203
|
+
};
|
|
204
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +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 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.0\";\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).\n// ============================================================\n\nconst sessions = new Map<string, string>(); // agentId -> sessionId\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\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 });\n const data = (await res.json()) as Record<string, unknown>;\n if (!res.ok) throw new Error(String((data as { error?: string }).error || `HTTP ${res.status}`));\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 const data = (await res.json()) as Record<string, unknown>;\n if (!res.ok) throw new Error(String((data as { error?: string }).error || `HTTP ${res.status}`));\n return data;\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 return lines.join(\"\\n\");\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 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: ${e instanceof Error ? e.message : String(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 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: ${e instanceof Error ? e.message : String(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 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: ${e instanceof Error ? e.message : String(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);\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// 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: [],\n evaluators: [],\n};\n\nexport default syndicatePlugin;\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "plugin-syndicate",
|
|
3
|
+
"version": "0.1.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. Humans and agents share one world and one leaderboard.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"module": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
"./package.json": "./package.json",
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js",
|
|
14
|
+
"default": "./dist/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"README.md",
|
|
20
|
+
"LICENSE"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsup",
|
|
24
|
+
"clean": "rm -rf dist",
|
|
25
|
+
"test": "vitest run"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"elizaos",
|
|
29
|
+
"elizaos-plugin",
|
|
30
|
+
"eliza",
|
|
31
|
+
"ai-agents",
|
|
32
|
+
"game",
|
|
33
|
+
"agent-gameplay",
|
|
34
|
+
"strategy",
|
|
35
|
+
"trading-cards",
|
|
36
|
+
"tcg",
|
|
37
|
+
"oracle-api",
|
|
38
|
+
"the-syndicate",
|
|
39
|
+
"undesirables"
|
|
40
|
+
],
|
|
41
|
+
"author": "The Undesirables LLC (sailorpepe)",
|
|
42
|
+
"license": "BUSL-1.1",
|
|
43
|
+
"homepage": "https://play.the-undesirables.com",
|
|
44
|
+
"repository": {
|
|
45
|
+
"type": "git",
|
|
46
|
+
"url": "git+https://github.com/sailorpepe/plugin-syndicate.git"
|
|
47
|
+
},
|
|
48
|
+
"peerDependencies": {
|
|
49
|
+
"@elizaos/core": "2.0.3-beta.7"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@elizaos/core": "2.0.3-beta.7",
|
|
53
|
+
"@types/node": "^25.6.0",
|
|
54
|
+
"tsup": "^8.5.1",
|
|
55
|
+
"typescript": "^5.4.0",
|
|
56
|
+
"vitest": "^3.0.0"
|
|
57
|
+
}
|
|
58
|
+
}
|