Skip to content

Commit ef8529e

Browse files
committed
make sure config is used consistently, start adding tests
1 parent be37d58 commit ef8529e

16 files changed

+232
-69
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@ venv/
55
client/node_modules/
66
client/out/
77
taleweave/custom_*
8+
.coverage
9+
coverage.*

docs/cli.md

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# TaleWeave AI Command Line Options
2+
3+
The following command line arguments are available when launching the TaleWeave AI engine:
4+
5+
- **--actions**
6+
- **Type:** String
7+
- **Description:** Additional actions to include in the simulation. Note: More than one argument is allowed.
8+
9+
- **--add-rooms**
10+
- **Type:** Integer
11+
- **Default:** 0
12+
- **Description:** The number of new rooms to generate before starting the simulation.
13+
14+
- **--config**
15+
- **Type:** String
16+
- **Description:** The file to load additional configuration from.
17+
18+
- **--discord**
19+
- **Action:** No options are needed for this argument. Simply passing the argument name is enough to enable this option.
20+
- **Description:** Run the simulation in a Discord bot.
21+
22+
- **--flavor**
23+
- **Type:** String
24+
- **Default:** ""
25+
- **Description:** Additional flavor text for the generated world.
26+
27+
- **--optional-actions**
28+
- **Action:** No options are needed for this argument. Simply passing the argument name is enough to enable this option.
29+
- **Description:** Include optional actions in the simulation.
30+
31+
- **--player**
32+
- **Type:** String
33+
- **Description:** The name of the character to play as.
34+
35+
- **--prompts**
36+
- **Type:** String
37+
- **Description:** The file to load game prompts from. Note: More than one argument is allowed.
38+
39+
- **--render**
40+
- **Action:** No options are needed for this argument. Simply passing the argument name is enough to enable this option.
41+
- **Description:** Run the render thread.
42+
43+
- **--render-generated**
44+
- **Action:** No options are needed for this argument. Simply passing the argument name is enough to enable this option.
45+
- **Description:** Render entities as they are generated.
46+
47+
- **--rooms**
48+
- **Type:** Integer
49+
- **Description:** The number of rooms to generate.
50+
51+
- **--server**
52+
- **Action:** No options are needed for this argument. Simply passing the argument name is enough to enable this option.
53+
- **Description:** Run the websocket server.
54+
55+
- **--state**
56+
- **Type:** String
57+
- **Description:** The file to save the world state to. Defaults to `$world.state.json` if not set.
58+
59+
- **--turns**
60+
- **Type:** Integer or "inf"
61+
- **Default:** 10
62+
- **Description:** The number of simulation turns to run.
63+
64+
- **--systems**
65+
- **Type:** String
66+
- **Description:** Extra systems to run in the simulation. Note: More than one argument is allowed.
67+
68+
- **--theme**
69+
- **Type:** String
70+
- **Default:** "fantasy"
71+
- **Description:** The theme of the generated world.
72+
73+
- **--world**
74+
- **Type:** String
75+
- **Default:** "world"
76+
- **Description:** The file to save the generated world to.
77+
78+
- **--world-template**
79+
- **Type:** String
80+
- **Description:** The template file to load the world prompt from.

taleweave/actions/planning.py

+11-7
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,14 @@
22
action_context,
33
get_agent_for_character,
44
get_current_turn,
5+
get_game_config,
56
get_prompt,
67
)
78
from taleweave.errors import ActionError
8-
from taleweave.models.config import DEFAULT_CONFIG
99
from taleweave.models.planning import CalendarEvent
1010
from taleweave.utils.planning import get_recent_notes
1111
from taleweave.utils.prompt import format_prompt
1212

13-
character_config = DEFAULT_CONFIG.world.character
14-
1513

1614
def take_note(fact: str):
1715
"""
@@ -22,11 +20,13 @@ def take_note(fact: str):
2220
fact: The fact to remember.
2321
"""
2422

23+
config = get_game_config()
24+
2525
with action_context() as (_, action_character):
2626
if fact in action_character.planner.notes:
2727
raise ActionError(get_prompt("action_take_note_error_duplicate"))
2828

29-
if len(action_character.planner.notes) >= character_config.note_limit:
29+
if len(action_character.planner.notes) >= config.world.character.note_limit:
3030
raise ActionError(get_prompt("action_take_note_error_limit"))
3131

3232
action_character.planner.notes.append(fact)
@@ -103,6 +103,8 @@ def summarize_notes(limit: int) -> str:
103103
limit: The maximum number of notes to keep.
104104
"""
105105

106+
config = get_game_config()
107+
106108
with action_context() as (_, action_character):
107109
notes = action_character.planner.notes
108110
if len(notes) == 0:
@@ -120,11 +122,11 @@ def summarize_notes(limit: int) -> str:
120122
)
121123

122124
new_notes = [note.strip() for note in summary.split("\n") if note.strip()]
123-
if len(new_notes) > character_config.note_limit:
125+
if len(new_notes) > config.world.character.note_limit:
124126
raise ActionError(
125127
format_prompt(
126128
"action_summarize_notes_error_limit",
127-
limit=character_config.note_limit,
129+
limit=config.world.character.note_limit,
128130
)
129131
)
130132

@@ -165,7 +167,9 @@ def check_calendar(count: int):
165167
count: The number of upcoming events to read. 5 is usually a good number.
166168
"""
167169

168-
count = min(count, character_config.event_limit)
170+
config = get_game_config()
171+
172+
count = min(count, config.world.character.event_limit)
169173
current_turn = get_current_turn()
170174

171175
with action_context() as (_, action_character):

taleweave/bot/discord.py

+13-11
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@
1111
broadcast,
1212
get_character_agent_for_name,
1313
get_current_world,
14+
get_game_config,
1415
set_character_agent,
1516
subscribe,
1617
)
17-
from taleweave.models.config import DEFAULT_CONFIG, DiscordBotConfig
18+
from taleweave.models.config import DiscordBotConfig
1819
from taleweave.models.event import (
1920
ActionEvent,
2021
GameEvent,
@@ -38,7 +39,6 @@
3839

3940
logger = getLogger(__name__)
4041
client = None
41-
bot_config: DiscordBotConfig = DEFAULT_CONFIG.bot.discord
4242

4343
active_tasks = set()
4444
event_messages: Dict[int, str | GameEvent] = {}
@@ -78,29 +78,32 @@ async def on_message(self, message):
7878
if message.author == self.user:
7979
return
8080

81+
config = get_game_config()
8182
author = message.author
8283
channel = message.channel
8384
user_name = author.name # include nick
8485

8586
if message.content.startswith(
86-
bot_config.command_prefix + bot_config.name_command
87+
config.bot.discord.command_prefix + config.bot.discord.name_command
8788
):
8889
world = get_current_world()
8990
if world:
9091
world_message = format_prompt(
91-
"discord_world_active", bot_name=bot_config.name_title, world=world
92+
"discord_world_active",
93+
bot_name=config.bot.discord.name_title,
94+
world=world,
9295
)
9396
else:
9497
world_message = format_prompt(
95-
"discord_world_none", bot_name=bot_config.name_title
98+
"discord_world_none", bot_name=config.bot.discord.name_title
9699
)
97100

98101
await message.channel.send(world_message)
99102
return
100103

101104
if message.content.startswith("!help"):
102105
await message.channel.send(
103-
format_prompt("discord_help", bot_name=bot_config.name_command)
106+
format_prompt("discord_help", bot_name=config.bot.discord.name_command)
104107
)
105108
return
106109

@@ -172,14 +175,11 @@ def prompt_player(event: PromptEvent):
172175

173176

174177
def launch_bot(config: DiscordBotConfig):
175-
global bot_config
176178
global client
177179

178-
bot_config = config
179-
180180
# message contents need to be enabled for multi-server bots
181181
intents = Intents.default()
182-
if bot_config.content_intent:
182+
if config.content_intent:
183183
intents.message_content = True
184184

185185
client = AdventureClient(intents=intents)
@@ -246,12 +246,14 @@ def get_active_channels():
246246
if not client:
247247
return []
248248

249+
config = get_game_config()
250+
249251
# return client.private_channels
250252
return [
251253
channel
252254
for guild in client.guilds
253255
for channel in guild.text_channels
254-
if channel.name in bot_config.channels
256+
if channel.name in config.bot.discord.channels
255257
]
256258

257259

taleweave/context.py

+15
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from pyee.base import EventEmitter
1919

2020
from taleweave.game_system import GameSystem
21+
from taleweave.models.config import DEFAULT_CONFIG, Config
2122
from taleweave.models.entity import Character, Room, World
2223
from taleweave.models.event import GameEvent, StatusEvent
2324
from taleweave.models.prompt import PromptLibrary
@@ -34,6 +35,7 @@
3435

3536
# game context
3637
event_emitter = EventEmitter()
38+
game_config: Config = DEFAULT_CONFIG
3739
game_systems: List[GameSystem] = []
3840
prompt_library: PromptLibrary = PromptLibrary(prompts={})
3941
system_data: Dict[str, Any] = {}
@@ -160,6 +162,10 @@ def get_dungeon_master() -> Agent:
160162
return dungeon_master
161163

162164

165+
def get_game_config() -> Config:
166+
return game_config
167+
168+
163169
def get_game_systems() -> List[GameSystem]:
164170
return game_systems
165171

@@ -172,6 +178,10 @@ def get_prompt_library() -> PromptLibrary:
172178
return prompt_library
173179

174180

181+
def get_system_config(system: str) -> Any | None:
182+
return game_config.systems.data.get(system)
183+
184+
175185
def get_system_data(system: str) -> Any | None:
176186
return system_data.get(system)
177187

@@ -209,6 +219,11 @@ def set_dungeon_master(agent):
209219
dungeon_master = agent
210220

211221

222+
def set_game_config(config: Config):
223+
global game_config
224+
game_config = config
225+
226+
212227
def set_game_systems(systems: Sequence[GameSystem]):
213228
global game_systems
214229
game_systems = list(systems)

taleweave/generate.py

+16-3
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,14 @@
77
from packit.results import enum_result, int_result
88
from packit.utils import could_be_json
99

10-
from taleweave.context import broadcast, get_prompt, set_current_world, set_system_data
10+
from taleweave.context import (
11+
broadcast,
12+
get_game_config,
13+
get_prompt,
14+
set_current_world,
15+
set_system_data,
16+
)
1117
from taleweave.game_system import GameSystem
12-
from taleweave.models.config import DEFAULT_CONFIG, WorldConfig
1318
from taleweave.models.effect import (
1419
EffectPattern,
1520
FloatEffectPattern,
@@ -33,7 +38,10 @@
3338

3439
logger = getLogger(__name__)
3540

36-
world_config: WorldConfig = DEFAULT_CONFIG.world
41+
42+
def get_world_config():
43+
config = get_game_config()
44+
return config.world
3745

3846

3947
def duplicate_name_parser(existing_names: List[str]):
@@ -112,6 +120,7 @@ def generate_room(
112120
actions = {}
113121
room = Room(name=name, description=desc, items=[], characters=[], actions=actions)
114122

123+
world_config = get_world_config()
115124
item_count = resolve_int_range(world_config.size.room_items) or 0
116125
broadcast_generated(
117126
format_prompt(
@@ -276,6 +285,7 @@ def generate_item(
276285
item = Item(name=name, description=desc, actions=actions)
277286
generate_system_attributes(agent, world, item, systems)
278287

288+
world_config = get_world_config()
279289
effect_count = resolve_int_range(world_config.size.item_effects) or 0
280290
broadcast_generated(
281291
message=format_prompt(
@@ -343,6 +353,7 @@ def generate_character(
343353
generate_system_attributes(agent, world, character, systems)
344354

345355
# generate the character's inventory
356+
world_config = get_world_config()
346357
item_count = resolve_int_range(world_config.size.character_items) or 0
347358
broadcast_generated(
348359
message=format_prompt(
@@ -499,6 +510,7 @@ def link_rooms(
499510
rooms: List[Room] | None = None,
500511
) -> None:
501512
rooms = rooms or world.rooms
513+
world_config = get_world_config()
502514

503515
for room in rooms:
504516
num_portals = resolve_int_range(world_config.size.portals) or 0
@@ -550,6 +562,7 @@ def generate_world(
550562
systems: List[GameSystem],
551563
room_count: int | None = None,
552564
) -> World:
565+
world_config = get_world_config()
553566
room_count = room_count or resolve_int_range(world_config.size.rooms) or 0
554567

555568
broadcast_generated(message=format_prompt("world_generate_world_broadcast_theme"))

taleweave/main.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,15 @@
2727

2828
logger = logger_with_colors(__name__) # , level="DEBUG")
2929

30-
load_dotenv(environ.get("ADVENTURE_ENV", ".env"), override=True)
30+
load_dotenv(environ.get("TALEWEAVE_ENV", ".env"), override=True)
3131

3232
if True:
3333
from taleweave.context import (
3434
get_prompt_library,
3535
get_system_data,
3636
set_current_turn,
3737
set_dungeon_master,
38+
set_game_config,
3839
set_system_data,
3940
subscribe,
4041
)
@@ -312,6 +313,7 @@ def main():
312313
if args.config:
313314
with open(args.config, "r") as f:
314315
config = Config(**load_yaml(f))
316+
set_game_config(config)
315317
else:
316318
config = DEFAULT_CONFIG
317319

0 commit comments

Comments
 (0)