* linting

* Add cleanup function for recent scenes in config to remove non-existent paths

* remove leghacy world state manager buttons

* move world state scene tools into sub component

* linting

* move module properties to navigation drawer

* Update icons in NodeEditorLibrary and NodeEditorModuleProperties for improved UI clarity

* prompt tweaks

* director chat prompt simplifications

* more prompt fixes

* Enhance type hints for duration conversion functions in time.py

* narrate time action now has access to response length instructions

* Add IsoDateDuration node for ISO 8601 interval string construction

* Update advance_time method to include return type annotation and return message

* Add AdvanceTime node to world state for time advancement with duration and narration instructions

* linting

* Add agent state exclusions to changelog with a TODO for module migration

* Add message emission for actor, narrator, and scene analysis guidance in respective components. Enhance AgentMessages and SceneTools for better message handling and visual feedback.

* Remove agent messages from state when opening agent message view in SceneTools component.

* linting

* openroute fetch models on key set

* Add input history functionality to message input in TalemateApp component. Implement keyboard shortcuts for navigating history (Ctrl+Up/Down) and limit history to the last 10 messages. Update message sending logic to store messages in history.

* Update message input hint in TalemateApp component to include keyboard shortcuts for navigating input history (Ctrl+Up/Down).

* node updates

* unified data extraction function

* prompt tweaks

* Add gamestate context support in BuildPrompt and corresponding template. Introduced new property for gamestate context and updated rendering logic to include gamestate information in prompts.

* Refactor Prompt class by removing LoopedPrompt and cleaning up related methods. Update data response parsing to streamline functionality and improve clarity. Adjust imports accordingly.

* Add 'data_multiple' property to GenerateResponse class to allow multiple data structures in responses. Update output socket type for 'data_obj' to support both dict and list formats.

* Add DictUpdate node

* Add UnpackGameState node to retrieve and unpack game state variables

* gamestate nodes

* linting

* Enhance scene view toggle functionality to support shift-click behavior for closing all drawers when hiding the scene view.

* immutable scenes should reset context db on load

* linting

* node updates

* prompt tweaks

* Add context type output and filtering for creative context ID meta entries in PathToContextID and ContextIDMetaEntries nodes

* Add string replacement functionality and Jinja2 formatting support in nodes. Introduced 'old' and 'new' properties for substring replacement in the Replace node, and added a new Jinja2Format node for template rendering using jinja2.

* Add additional outputs for context validation in ValidateContextIDItem node, including context type, context value, and name.

* prompt tweaks

* node adjustments

* linting

* Add data_expected attribute to Focal and Prompt classes for enhanced response handling

* node updates

* node updates

* node updates

* prompt tweaks

* director summary return appropriately on no action taken

* Enhance action handling in DirectorChatMixin by skipping actions when a question is present in the parsed response, ensuring better response accuracy.

* Enhance ConfirmActionPrompt component by adding anchorTop prop for dynamic alignment and adjusting icon size and color for improved UI consistency.

* anchor clear chat confirm to top

* responsive layout fixes in template editors

* linting

* relock

* Add scene progression guidance to chat-common-tasks template

* Refactor push_history method to be asynchronous across multiple agents and scenes, ensuring consistent handling of message history updates.

* Update chat instructions to clarify user intent considerations and enhance decisiveness in responses. Added guidance on distinguishing between scene progression and background changes, and refined analysis requirements for user interactions.

* Enhance DirectorConsoleChatsToolbar by adding a usage cheat sheet tooltip for user guidance and refining the Clear Chat button's UI for better accessibility.

* store character data at unified point

* fix button

* fix world editor auto sync

* Shared context 2 (#19)

Shared context

* Refactor NodeEditorLibrary to improve search functionality and debounce input handling. Updated v-text-field model and added a watcher for search input to enhance performance.

* Refactor NodeEditor and TalemateApp components to enhance UI interactions. Removed the exit creative mode button from NodeEditor and updated tooltips for clarity. Adjusted app bar navigation icons for better accessibility and added functionality to switch between node editor and creative mode.

* comment

* Character.update deserialize voice value correctly

* Enhance SharedContext.update_to_scene method to properly add or update character data in the scene based on existence checks. This improves the synchronization of character states between shared context and scene.

* shared context static history support
fix context memory db imports to always import

* Update WorldStateManagerSceneSharedContext.vue to clarify sharing of character, world entries, and history across connected scenes.

* linting

* Enhance chat modes by adding 'nospoilers' option to DirectorChat and related payloads. Update chat instructions to reflect new mode behavior and improve UI to support mode-specific icons and colors in the DirectorConsoleChatsToolbar.

* Comment out 'repetition_penalty_range' in TabbyAPIClient to prevent unexpected "<unk><unk> .." responses. Further investigation needed.

* linting

* Add active_characters and intro_instructions to Inheritance model; implement intro generation in load_scene_from_data. Update WorldStateManagerSceneSharedContext.vue to enhance new scene creation dialog with character selection and premise instructions.

* rename inheritance to scene initialization

* linting

* Update WorldStateManagerSceneSharedContext.vue to conditionally display alert based on scene saving status and new scene creation state.

* Refine messages for shared context checkboxes in WorldStateManagerCharacter and WorldStateManagerWorldEntries components for clarity.

* Add scene title generation to load process and update contextual generation template. Introduced a new method in AssistantMixin for generating scene titles, ensuring titles are concise and free of special characters. Updated load_scene_from_data to assign generated titles to scenes.

* linting

* Refactor GameState component to integrate Codemirror for JSON editing, replacing the previous treeview structure. Implement validation for JSON input and enhance error handling. Remove unused methods and streamline state management.

* Add lastLoadedJSON property to GameState component for change detection. Update validation logic to prevent unnecessary updates when game state has not changed.

* Remove status emission for gameplay switch in CmdSetEnvironmentToScene class.

* allow individual sharing of attributes and details

* linting

* Remove redundant question handling logic in DirectorChatMixin to streamline action selection process.

* Update EXTERNAL_DESCRIPTION in TabbyAPI client to include notes on EXL3 model sensitivity to inference parameters. Adjust handling of 'repetition_penalty_range' in parameter list for clarity.

* director chat support remove message and regenerate message

* Refactor ConfirmActionInline component to improve button rendering logic. Introduced 'size' prop for button customization and added 'comfortable' density option. Simplified icon handling with computed property for better clarity.

* linting

* node updates

* Add appBusy prop to DirectorConsoleChats and DirectorConsoleChatsToolbar components to manage button states during busy operations.

* Refactor DirectorChatMixin to utilize standalone utility functions for parsing response sections and extracting action blocks. This improves code clarity and maintainability. Added tests for new utility functions in test_utils_prompt.py to ensure correct functionality.

* Update clear chat button logic to consider appBusy state in DirectorConsoleChatsToolbar component, enhancing user experience during busy operations.

* linting

* Remove plan.md

* Add chat template identifier support and error handling in ModelPrompt class

- Implemented logic to check for 'chat_template.jinja2' in Hugging Face repository.
- Added new template identifiers: GraniteIdentifier and GLMIdentifier.
- Enhanced error handling to avoid logging 404 errors for missing templates.
- Introduced Granite.jinja2 template file for prompt structure.

* node fixes

* remove debug msg

* Enhance error handling in DynamicInstruction class by enforcing header requirement and ensuring content defaults to an empty string if not provided.

* recet scene message visibility on scene load

* prompt tweaks

* Enhance data extraction in Focal class by adding a fallback mechanism. Implemented additional error handling to attempt data extraction from a fenced block if the initial extraction fails, improving robustness in handling responses.

* linting

* node fixes

* Add relative_to_root function for path resolution and update node export logic

- Introduced a new function `relative_to_root` in path.py to resolve paths relative to the TALEMATE_ROOT.
- Updated the `export_node_definitions` function in registry.py to use `relative_to_root` for module path resolution.
- Added a check to skip non-selectable node definitions in litegraphUtils.js during registration.

* show icons

* Improve error handling in export_node_definitions by adding a try-except block for module path resolution. Log a warning if the relative path conversion fails.

* typo

* Refactor base_attributes type in Character model to a more generic dict type for improved flexibility

* relock

* ensure character gets added to character_data

* prompt tweaks

* linting

* properly activate characters

* activate needs to happen explicitly now and deactivated is the default

* missing arg

* avoid changed size error

* Refactor character removal logic in shared context to prevent deletion; characters are now only marked as non-shared.

* Add update_from_scene method calls in SharedContextMixin for scene synchronization

* Add ensure_changelogs_for_all_scenes function to manage changelog files for all scenes; integrate it into the server run process.

* Enhance backup restore functionality by adding base and latest snapshot options; improve UI with clearer labels and alerts for restore actions.

* Update _apply_delta function to enhance delta application handling by adding parameters for error logging and force application of changes on non-existent paths.

* Skip processing of changelog files in _list_files_and_directories function to prevent unnecessary inclusion in file listings.

* Update IntroRecentScenes.vue to use optional chaining for selectedScene properties and enhance backup timestamp display with revision info.

* linting

* Refactor source entry attribute access in collect_source_entries function to use getattr for optional attributes, improving robustness.

* Implement logic to always show scene view in scene mode within TalemateApp.vue, enhancing user experience during scene interactions.

* prompt tweaks

* prompt tweaks

* Update TalemateApp.vue to set the active tab to 'main' when switching to the node editor, improving navigation consistency.

* Add active frontend websocket handler management in websocket_endpoint

* agent websocket handler node support

* Refactor init_nodes method in DirectorAgent to call superclass method and rename chat initialization method in DirectorChatMixin for clarity.

* Add characters output to ContextHistory node to track active participants in the scene

* Add Agent Websocket Handler option to Node Editor Library with corresponding icons and labels

* Add check for node selectability in NodeEditorNodeSearch component to filter search results accordingly.

* Add SummarizeWebsocketHandler to handle summarize actions and integrate it into SummarizeAgent

* nodes

* Add data property to QueueResponse class for websocket communication and update run method to include action and data in output values.

* Update manual context handling in WorldStateManager to include shared property from existing context

* Enhance GetWorldEntry node to include 'shared' property in output values from world entry context

* Update scene loading to allow setting scene ID from data and include ID in scene serialization

* Update icon for AgentWebsocketHandler in NodeEditorLibrary component to mdi-web-box

* Refactor WorldStateManager components to enhance history management and sharing capabilities. Added summarized history titles, improved UI for sharing static history, and integrated scene summarization functionality. Removed deprecated methods related to shared context settings.

* linting

* Change log level from warning to debug for migrate_narrator_source_to_meta error handling in NarratorMessage class.

* Update GLM-no-reasoning template to include <think></think> tag before coercion message for improved prompt structure.

* allow prompt templates to specify reasoning pattern

* Add Seed.jinja2 template for LLM prompts with reasoning patterns and user interaction handling

* Enhance NarratorAgent to support dynamic response length configuration. Updated max generation length from 192 to 256 tokens and introduced a new method to calculate response length. Modified narration methods to accept and utilize response length parameter. Added response length property in GenerateNarrationBase class and updated templates to include response length handling.

* Update response length calculation in RevisionMixin to include token count for improved text processing.

* Refactor response identifier in RevisionMixin to dynamically use calculated response length for improved prompt handling.

* linting

* allow contextual generation of static history entries

* Add is_static property to HistoryEntry for static history entry identification

* Add "static history" option to ContextualGenerate node for enhanced contextual generation capabilities.

* Add CreateStaticArchiveEntry and RemoveStaticArchiveEntry nodes for managing static history entries. Implement input/output properties and error handling for entry creation and deletion.

* nodes updated

* linting

* Add assets field to SceneInitialization model and update load_scene_from_data function to handle scene assets. Update WorldStateManagerSceneSharedContext.vue to include assets in scene initialization parameters.

* Refactor CoverImage component to enhance drag-and-drop functionality and improve styling for empty portrait state.

* Add intent_state to SceneInitialization model and update load_scene_from_data function to handle intent state. Introduce story_intent property in Scene class and reset method in SceneIntent class. Update WorldStateManagerSceneSharedContext.vue to include intent state in scene initialization parameters.

* Refactor WorldStateManagerSceneSharedContext.vue to improve cancel functionality by introducing a dedicated cancelCreate method and removing the direct dialog toggle from the Cancel button. This enhances code clarity and maintainability.

* Update SharedContext to use await for set_shared method, ensuring proper asynchronous handling when modifying character sharing status.

* Add MAX_CONTENT_WIDTH constant and update components to use it for consistent max width styling

* fix issue with data structure parsing

* linting

* fix tests

* nodes

* fix update_introduction

* Add building blocks template for story configuration and scene management

* Refactor toggleNavigation method to accept an 'open' parameter for direct control over drawer visibility in TalemateApp.vue

* Update usageCheatSheet text in DirectorConsoleChatsToolbar.vue for clarity and add pre-wrap styling to tooltip

* Add cover image and writing style sections to story and character templates; update chat common tasks with new scene restrictions and user guide reference.

* linting

* relock

* Add EmitWorldEditorSync node to handle world editor synchronization; update WorldStateManager to refresh active tab on sync action.

* Update Anthropic client with new models and adjust default settings; introduce limited parameter models for specific configurations.

* director action  module updates

* direct context update fn

* director action updates

* Update usageCheatSheet in DirectorConsoleChatsToolbar.vue to include recommendation for 100B+ models.

* Remove debug diagnostics from DirectorConsoleChats.vue to clean up console output.

* Update card styles in IntroRecentScenes.vue for improved visual consistency; change card color to grey-darken-3 and adjust text classes for titles and subtitles.

* Update EmitWorldEditorSync node to include websocket passthrough in sync action for improved event handling.

* Increase maximum changelog file size limit from 500KB to 1MB to accommodate larger change logs.

* linting

* director action module updates

* 0.33 added

* Add Nexus agent persona to talemate template and initialize phrases array

* Add support for project-specific grouping in NodeEditorLibrary for templates/modules, enhancing organization of node groups.

* docs

* Enhance NodeEditorLibrary by adding primary color to tree component for improved visibility and user experience.

* docs

* Enhance NewSceneSetupModal to include subtitles for writing styles and director personas, improving context and usability.

* Update agent persona description in WorldStateManagerTemplates to specify current support for director only, enhancing clarity for users.

* Refine agent persona description in WorldStateManagerTemplates to clarify assignment per agent in Scene Settings, maintaining focus on current director-only support.

* fix crash when attempting to delete some clients

* Add TODO comments in finalize_llama3 and finalize_YI methods to indicate removable cruft

* Add lock_template feature to Client configuration and update related components for template management

* linting

* persist client template lock through model changes

* There is no longer a point to enforcing creative mode when there are no characters

* fix direct_narrator character argument

* Update CharacterContextItem to allow 'value' to accept dict type in addition to existing types

* docs

* Update lock_template field in Client model to allow None type in addition to bool

* Remove unused template_file field from Defaults model in Client configuration

* Refactor lock_template field in Client model and ClientModal component to ensure consistent boolean handling

* Add field validator for lock_template in Client model to ensure boolean value is returned

* fix issue where valid data processed in extract_data_with_ai_fallback was not returned

* Update default_player_character assignment in ConfigPlugin to use GamePlayerCharacter schema for improved data validation

* linting

* add heiku 4.5 model and make default

* opse 4.5 isnt a thing

* fix issue where  fork / restore would restore duplicate messages

* improve autocomplete handling when prefill isn't available

* prompt tweaks

* linting

* gracefully handle removed attributes

* Refactor scene reference handling in delete_changelog_files to prevent incorrect deletions. Added a test to verify proper scene reference construction and ensure changelog files are deleted correctly.

* forked scenes reset memory id and are not immutable

* emit_status export rev

* Update RequestInput.vue to handle extra_params more robustly, ensuring defaults are set correctly for input.

* only allow forking on saved messages

* linting

* tweak defaults

* summarizer fire off of push_history.after

* docs

* : in world entry titles will now load correctly

* linting

* docs

* removing base attrib ute or detail also clears it from shared list

* fix issue where cancelling some generations would cause errors

* increase font size

* formatting fixes

* unhandled errors at the loop level should not crash the entire scene

* separate message processing from main loop

* linting

* remove debug cruft

* enhance error logging in background processing to include traceback information

* linting

* nothing to detemrine of no model is sent

* fix some errors during kcpp client deletion

* improve configuration issue alert visibility

* restore input focus after autocomplete

* linting
This commit is contained in:
veguAI
2025-10-25 14:06:55 +03:00
committed by GitHub
parent 72867c930e
commit 89d16ae513
331 changed files with 53018 additions and 4084 deletions

3
.gitignore vendored
View File

@@ -31,4 +31,5 @@ scenes/
!scenes/infinity-quest/infinity-quest.json
tts_voice_samples/*.wav
third-party-docs/
legacy-state-reinforcements.yaml
legacy-state-reinforcements.yaml
CLAUDE.md

View File

@@ -12,14 +12,6 @@
!!! note "First start can take a while"
The initial download and dependency installation may take several minutes, especially on slow internet connections. The console will keep you updated just wait until the Talemate logo shows up.
### Optional: CUDA support
If you have an NVIDIA GPU and want CUDA acceleration for larger embedding models:
1. Close Talemate (if it is running).
2. Double-click **`install-cuda.bat`**. This script swaps the CPU-only Torch build for the CUDA 12.8 build.
3. Start Talemate again via **`start.bat`**.
## Maintenance & advanced usage
| Script | Purpose |

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

@@ -0,0 +1,125 @@
# Director Chat
!!! example "Experimental"
Currently experimental and may change substantially in the future.
Introduced in version 0.33.0 the director chat feature allows you interact with the director agent directly once a scene is loaded.
As part of the chat session the director can query for information as well as make changes to the scene.
!!! warning "Strong model recommended"
In my personal testing I've found that while its possible to have a coherent chat session with weaker models, the experience is going to be
significantly better with [reasoning enabled](/talemate/user-guide/clients/reasoning/) models past the 100B parameter mark.
This may change as smaller models get stronger and your mileage may vary.
!!! info "Chat settings"
You can customize various aspects of the director chat behavior in the [Director Chat settings](/talemate/user-guide/agents/director/settings/#director-chat), including response length, token budgets, and custom instructions.
## Accessing the director chat
Once a scene is loaded click the **:material-bullhorn:** director console icon in the top right corner of the screen.
![Director Console](/talemate/img/0.33.0/open-director-console.png)
![Director Console](/talemate/img/0.33.0/director-console-chat.png)
## Chat interface
The director chat provides a conversational interface where you can ask the director to perform various tasks, from querying information about your scene to making changes to characters, world entries, and progressing the story.
![Director Chat Interaction](/talemate/img/0.33.0/director-chat-interaction.png)
### What can you ask the director to do?
The director can help you with many tasks:
- Progress the story by generating new narration or dialogue
- Answer questions about your characters, world, or story details
- Create or modify characters, world entries, and story configuration
- Advance time in your story
- Manage game state variables (if your story uses them)
Simply describe what you want in natural language, and the director will figure out how to accomplish it.
### Viewing action details
When the director performs an action, you can expand it to see exactly what was done:
![Expanded Function Call](/talemate/img/0.33.0/director-chat-expanded-function-call.png)
This gives you full transparency into the changes being made to your scene.
## Chat modes
The director chat supports three different modes that control how the director behaves:
![Chat Mode Selection](/talemate/img/0.33.0/director-chat-mode.png)
!!! note
Chat mode behavior is not guaranteed and depends heavily on the model's ability to follow instructions. Stronger models, especially those with reasoning capabilities, will respect these modes much more consistently than weaker models.
### Normal mode
The default mode where the director can freely discuss the story and reveal information. It will ask for clarification when needed and take a more conversational approach.
### Decisive mode
In this mode, the director acts more confidently on your instructions and avoids asking for clarifications unless strictly necessary. Use this when you trust the director to make the right decisions autonomously.
### No Spoilers mode
This mode prevents the director from revealing information that could spoil the story. The director will still make changes and answer questions, but will be careful not to discuss plot points or details that should remain hidden.
## Write action confirmation
By default, the director will ask for confirmation before performing actions that modify your scene (like progressing the story or making significant changes).
![Confirm On](/talemate/img/0.33.0/director-chat-confirm-on.png)
You can toggle this behavior to allow the director to act without confirmation:
![Confirm Off](/talemate/img/0.33.0/director-chat-confirm-off.png)
!!! tip
Keep confirmation enabled when experimenting or when you want more control over changes. Disable it when you trust the director to act autonomously.
### Confirmation workflow example
When confirmation is enabled, the director will describe what it plans to do and wait for your approval:
![Confirmation Request](/talemate/img/0.33.0/director-chat-0001.png)
The confirmation dialog shows the instructions that will be sent and the expected result:
![Confirmation Dialog](/talemate/img/0.33.0/director-chat-0002.png)
Once confirmed, the action executes and new content is added to your scene:
![Action Approved](/talemate/img/0.33.0/director-chat-0003.png)
The director then analyzes the result and discusses what happened:
![Result Analysis](/talemate/img/0.33.0/director-chat-0004.png)
### Rejecting actions
You can also reject actions if you change your mind or want to revise your request:
![Action Rejection Request](/talemate/img/0.33.0/director-chat-reject-0001.png)
When rejected, the director acknowledges and waits for your next instruction:
![Action Rejected](/talemate/img/0.33.0/director-chat-reject-0002.png)
## Director personas
You can customize the director's personality and initial greeting by assigning a persona:
![Persona Selection](/talemate/img/0.33.0/director-chat-persona-0001.png)
Personas can completely change how the director presents itself and communicates with you:
![Persona Example](/talemate/img/0.33.0/director-chat-persona-0002.png)
To create or manage personas, select "Manage Personas" from the persona dropdown. You can define a custom description and initial chat message for each persona.

View File

@@ -154,4 +154,56 @@ Allows the director to evaluate the current scene phase and switch to a differen
The number of turns between evaluations. (0 = NEVER)
!!! note "Recommended to leave at 0 (never)"
This isn't really working well at this point, so recommended to leave at 0 (never)
This isn't really working well at this point, so recommended to leave at 0 (never)
## Director Chat
!!! example "Experimental"
Currently experimental and may change substantially in the future.
The [Director Chat](/talemate/user-guide/agents/director/chat) feature allows you to interact with the director through a conversational interface where you can ask questions, make changes to your scene, and direct story progression.
![Director Chat Settings](/talemate/img/0.33.0/director-agent-chat-settings.png)
##### Enable Analysis Step
When enabled, the director performs an internal analysis step before responding. This helps the director think through complex requests and plan actions more carefully.
!!! tip "Recommended for complex tasks"
Enable this when working on complex scene modifications or when you want more thoughtful responses. Disable it for simple queries to get faster responses.
##### Response token budget
Controls the maximum number of tokens the director can use for generating responses. Higher values allow for more detailed responses but use more tokens. Default is 2048.
##### Auto-iteration limit
The maximum number of action-response cycles the director can perform in a single interaction. For example, if set to 10, the director can execute actions and generate follow-up responses up to 10 times before requiring your input again. Default is 10.
##### Retries
The number of times the director will retry if it encounters an error during response generation. Default is 1.
##### Scene context ratio
Controls the fraction of the remaining token budget (after fixed context and instructions) that is reserved for scene context. The rest is allocated to chat history.
- **Lower values** (e.g., 0.30): 30% for scene context, 70% for chat history
- **Higher values** (e.g., 0.70): 70% for scene context, 30% for chat history
Default is 0.30.
##### Stale history share
When the chat history needs to be compacted (summarized), this controls what fraction of the chat history budget is treated as "stale" and should be summarized. The remaining portion is kept verbatim as recent messages.
- **Lower values** (e.g., 0.50): Summarize less (50%), keep more recent messages verbatim
- **Higher values** (e.g., 0.90): Summarize more (90%), keep fewer recent messages verbatim
Default is 0.70 (70% will be summarized when compaction is triggered).
##### Custom instructions
Add custom instructions that will be included in all director chat prompts. Use this to customize the director's behavior for your specific scene or storytelling style.
For example, you might add instructions to maintain a particular tone, follow specific genre conventions, or handle certain types of requests in a particular way.

View File

@@ -0,0 +1,70 @@
# Template Locking
Template locking allows you to prevent a client's prompt template from automatically updating when the model changes. This is useful when you want to maintain a consistent prompt format across different models or when you've customized a template for a specific use case.
## What is Template Locking?
By default, Talemate automatically determines the appropriate prompt template for each model you load. When you switch models, the prompt template updates to match the new model's requirements. Template locking disables this automatic behavior, keeping your selected template fixed regardless of model changes.
## When to Use Template Locking
Some models have reasoning and non-reasoning variants of their templates. This allows you to lock one client to the reasoning template and another to the non-reasoning template.
## How to Lock a Template
### Step 1: Open Client Settings
Start with your client that has a template already assigned (either automatically detected or manually selected):
![Lock Template - Starting Point](/talemate/img/0.33.0/client-lock-template-0001.png)
1. Open the client settings by clicking the cogwheels icon next to the client
2. Review the currently assigned template in the preview area
### Step 2: Enable Template Lock
When you check the **Lock Template** checkbox, the current template selection is cleared and you must select which template to lock:
![Lock Template - Select Template](/talemate/img/0.33.0/client-lock-template-0002.png)
1. Check the **Lock Template** checkbox
2. You'll see the message: "Please select a prompt template to lock for this client"
3. Select your desired template from the dropdown menu
This gives you the opportunity to choose which specific template you want to lock, rather than automatically locking whatever template happened to be active.
### Step 3: Template Locked
Once you've selected a template and clicked **Save**:
![Lock Template - Locked](/talemate/img/0.33.0/client-lock-template-0003.png)
- The template display shows your locked template with its name (e.g., `TextGenWebUI__LOCK.jinja2`)
- The template will no longer automatically update when you change models
- The lock icon indicates the template is fixed
## Understanding the Lock Template Setting
When the **Lock Template** checkbox is enabled:
- The prompt template will not automatically update when you change models
When disabled:
- Talemate automatically determines the best template for your loaded model
- Templates update when you switch models
- The system attempts to match templates via HuggingFace metadata
## Unlocking a Template
To return to automatic template detection:
1. Open the client settings
2. Uncheck the **Lock Template** checkbox
3. Click **Save**
4. Re-open the client settings and confirm that the template is no longer locked and the correct template is selected.
## Related Topics
- [Prompt Templates](/talemate/user-guide/clients/prompt-templates/) - Learn more about how prompt templates work
- [Client Configuration](/talemate/user-guide/clients/) - General client setup and configuration

View File

@@ -14,7 +14,7 @@ We **do not** care about changing any of the actual loop logic.
With this in mind we can extend a new scene loop from the default talemate loop. This will give us a copy of the default loop that we can add to while keeping the rest of the loop logic up to date with any future improvements.
The `scene-loop` module should already be selected in the **:material-group: Modules** library.
The `scene-loop` module should already be selected in the **:material-tree-view: Modules** library.
![Scene Loop](./img/2-0001.png)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -0,0 +1,333 @@
# Collector Nodes
!!! info "New in version 0.33"
Collector nodes with dynamic sockets were introduced in Talemate version 0.33.0.
Collector nodes are specialized nodes that aggregate multiple inputs into a single data structure. They feature **dynamic sockets** that can be added or removed as needed, making them flexible for various data aggregation scenarios.
## Types of Collector Nodes
### Dict Collector
![Dict Collector](../img/dict-collector.png)
**Expected output from the example above:**
```json
{
"some_variable": "hello",
"auto_save": true
}
```
The **Dict Collector** node collects key-value pairs into a dictionary.
**Inputs:**
- `dict` (optional): An existing dictionary to add items to
- `item{i}` (dynamic): Multiple dynamic input slots for key-value pairs
**Outputs:**
- `dict`: The resulting dictionary containing all collected key-value pairs
**How it works:**
1. Each dynamic input can accept either:
- A **tuple** in the format `(key, value)` from nodes like [Make Key-Value Pair](../img/dict-collector.png)
- Any **value**, in which case the key is inferred from the connected node's properties
2. When a tuple `(key, value)` is provided, the key and value are directly added to the dictionary
3. When a non-tuple value is provided, the collector attempts to infer the key name by checking the source node for:
- A `name` property/input
- A `key` property/input
- An `attribute` property/input
- Falls back to the socket name if none are found
4. The final dictionary contains all collected key-value pairs
**Common use cases:**
- Collecting multiple values into a structured dictionary
- Building configuration objects from separate nodes
- Aggregating character properties or attributes
- Creating data structures from unpacked objects
### List Collector
![List Collector](../img/list-collector.png)
**Expected output from the example above:**
```json
["hello", "world"]
```
The **List Collector** node collects items into a list.
**Inputs:**
- `list` (optional): An existing list to append items to
- `item{i}` (dynamic): Multiple dynamic input slots for list items
**Outputs:**
- `list`: The resulting list containing all collected items
**How it works:**
1. Each dynamic input accepts any value type
2. Values are appended to the list in the order of the dynamic inputs (item0, item1, item2, etc.)
3. If an existing list is provided, new items are appended to it
4. If no list is provided, a new empty list is created
**Common use cases:**
- Collecting multiple values into an ordered list
- Aggregating results from multiple nodes
- Building lists for iteration or processing
- Combining outputs from multiple sources
## Managing Dynamic Sockets
Collector nodes support **dynamic input sockets** that can be added or removed as needed.
### Adding Input Sockets
There are two ways to add input sockets:
1. **Using the on-node buttons**: Click the green **+** button at the bottom of the node
2. **Using the context menu**: Right-click the node and select `Add Input Slot`
### Removing Input Sockets
There are two ways to remove input sockets:
1. **Using the on-node buttons**: Click the red **-** button at the bottom of the node (removes the last dynamic input)
2. **Using the context menu**: Right-click the node and select `Remove Last Input`
!!! note "Only the last dynamic input can be removed"
You can only remove the most recently added dynamic input. To remove an input from the middle, you must first remove all inputs after it.
## Working with Key-Value Pairs
When working with **Dict Collector**, you'll often use the **Make Key-Value Pair** node to create properly formatted tuple outputs.
**Make Key-Value Pair Node:**
- **Inputs**: `key` (string), `value` (any type)
- **Outputs**: `kv` (tuple), `key` (string), `value` (any)
The `kv` output produces a tuple in the format `(key, value)` which can be directly connected to Dict Collector's dynamic inputs.
**Example:**
```
[Make Key-Value Pair] [Make Key-Value Pair] [Get State]
key: "name" key: "age" scope: local
value: "Alice" value: 30 name: "works"
↓ kv ↓ kv ↓ value
└────────┐ ┌─────┘ │
↓ ↓ ↓
[Dict Collector] [Dict Collector]
item0 item1 item2
{"name": "Alice", "age": 30, "works": true}
```
## Nested Collection
Collector nodes can be chained together to create nested data structures:
- **Dict into Dict**: A Dict Collector's output can feed into another Dict Collector's `dict` input to add more key-value pairs
- **List into List**: A List Collector's output can feed into another List Collector's `list` input to combine lists
- **Mixed nesting**: Lists can contain dictionaries and vice versa
**Example of nested collection:**
```
[Dict Collector A] → [Dict Collector B]
item0: ("x", 10) dict: (from A)
item1: ("y", 20) item0: ("z", 30)
Result: {"x": 10, "y": 20, "z": 30}
```
## Examples
### Dict Collector Example
In the Dict Collector screenshot above, two nodes are connected:
- **item0**: `value` output from "GET local.some_variable"
- **item1**: `auto_save` output from "Get Scene State"
Since no explicit key-value tuples are provided, the Dict Collector uses key inference:
- **item0**: Infers key from the source node's `name` property → `"some_variable"`
- **item1**: Uses the socket name → `"auto_save"`
**Expected output:**
```python
{
"some_variable": <value from local.some_variable>,
"auto_save": <value from scene state's auto_save property>
}
```
For example, if `local.some_variable` contains `"hello"` and `auto_save` is `True`:
```python
{
"some_variable": "hello",
"auto_save": True
}
```
### List Collector Example
In the List Collector screenshot above, two Get State nodes are connected:
- **item0**: `value` from "GET local.some_variable"
- **item1**: `value` from "GET local.other_variable"
The List Collector simply appends values in order.
**Expected output:**
```python
[
<value from local.some_variable>,
<value from local.other_variable>
]
```
For example, if `local.some_variable` contains `"hello"` and `local.other_variable` contains `"world"`:
```python
["hello", "world"]
```
## String Formatting with Collected Data
Collector nodes work seamlessly with formatting nodes to convert collected data into formatted strings. Two powerful formatting nodes that support dynamic inputs are **Advanced Format** and **Jinja2 Format**.
### Advanced Format
![Advanced Format](../img/advanced-format.png)
**Expected output from the example above:**
```json
"hello world"
```
The **Advanced Format** node uses Python-style string formatting with dynamic inputs similar to Dict Collector.
!!! warning "Use single curly braces `{}`"
Advanced Format uses Python's `.format()` syntax. Variables are referenced with **single curly braces**: `{variable_name}`
**Inputs:**
- `template` (required): A format string with placeholders (e.g., `"hello {hello}"`)
- `variables` (optional): Base dictionary to merge with dynamic inputs
- `item{i}` (dynamic): Multiple dynamic input slots for format variables
**Outputs:**
- `result`: The formatted string
**How it works:**
1. Each dynamic input can accept either:
- A **tuple** in the format `(key, value)`
- Any **value**, in which case the key is inferred from the connected node's properties (same logic as Dict Collector)
2. Variables from dynamic inputs are merged with the optional `variables` dictionary
3. The template is formatted using Python's `.format()` method with all collected variables
4. Placeholders in the template like `{hello}` are replaced with their corresponding values
**Example from screenshot:**
- Template: `"hello {hello}"`
- Dynamic input `item0`: Connected to "GET local.hello" which has value `"world"`
- Key inferred as `"hello"` from the source node's `name` property
- Result: `"hello world"`
### Jinja2 Format
![Jinja2 Format](../img/jinja2-format.png)
**Expected output from the example above:**
```json
"hello world"
```
The **Jinja2 Format** node extends Advanced Format but uses Jinja2 templating instead of Python's `.format()`.
!!! warning "Use double curly braces `{{}}`"
Jinja2 Format uses Jinja2 template syntax. Variables are referenced with **double curly braces**: `{{ variable_name }}`
**Inputs:**
- `template` (required): A Jinja2 template string (e.g., `"hello {{ hello }}"`)
- `variables` (optional): Base dictionary to merge with dynamic inputs
- `item{i}` (dynamic): Multiple dynamic input slots for template variables
**Outputs:**
- `result`: The rendered template string
**How it works:**
1. Inherits all the dynamic input behavior from Advanced Format
2. Uses Jinja2 template syntax: `{{ variable }}` for variables, `{% %}` for logic
3. Supports all Jinja2 features: filters, conditionals, loops, etc.
4. Perfect for complex formatting needs beyond simple placeholder replacement
**Example from screenshot:**
- Template: `"hello {{ hello }}"`
- Dynamic input `item0`: Connected to "GET local.hello" with value `"world"`
- Key inferred as `"hello"` from the source node's `name` property
- Result: `"hello world"`
### Combining Collectors with Formatters
A common pattern is to use collectors to gather data, then format it into strings:
```
[Get State] ──→ [Dict Collector] ──→ [Advanced Format]
[Get State] ──→ item0 variables
item1 ↓
↓ template: "Name: {name}, Age: {age}"
{"name": "Alice",
"age": 30}
```
Or use dynamic inputs directly on the formatter:
```
[Get State] ──→ [Advanced Format]
[Get State] ──→ item0
item1
template: "{name} is {age} years old"
```
### Format vs Advanced Format vs Jinja2 Format
| Feature | Format | Advanced Format | Jinja2 Format |
|---------|--------|-----------------|---------------|
| **Dynamic Inputs** | No | Yes | Yes |
| **Syntax** | Python `.format()` | Python `.format()` | Jinja2 `{{ }}` |
| **Key Inference** | No | Yes | Yes |
| **Conditionals** | No | No | Yes |
| **Loops** | No | No | Yes |
| **Filters** | No | No | Yes |
| **Best For** | Simple static formatting | Dynamic formatting with multiple inputs | Complex templates with logic |

View File

@@ -1,5 +1,8 @@
# Prompt Templates
!!! tip "Want a more streamlined approach?"
If you need quick prompts with automatic context management, check out [Prompt Building](prompt_building.md) for a simplified alternative to manual template construction.
Prompt templates in the node editor allow you to create dynamic, reusable prompts that can be customized with variables and sent to agents for processing.
## Overview

View File

@@ -0,0 +1,191 @@
# Prompt Building
!!! info "New in version 0.33"
The Build Prompt node was introduced in Talemate version 0.33.0.
The **Build Prompt** node is a high-level alternative to manually constructing prompts with templates. It automatically assembles prompts with contextual information based on configurable needs, making it much faster to create agent prompts without managing template files.
## Build Prompt vs Prompt Templates
While [Prompt Templates](prompt-templates.md) give you complete control over every aspect of your prompt construction, **Build Prompt** provides a streamlined approach:
| Feature | Build Prompt | Prompt Templates |
|---------|--------------|------------------|
| **Complexity** | Simple configuration | Full template control |
| **Context Management** | Automatic | Manual |
| **Token Budgeting** | Built-in | Manual calculation |
| **Setup Time** | Fast | Requires template creation |
| **Flexibility** | Predefined options | Complete customization |
| **Best For** | Quick prompts, standard patterns | Complex custom prompts |
**Use Build Prompt when:**
- You need standard contextual prompts quickly
- You want automatic context and memory management
- You're using common prompt patterns (analysis, direction, creation, etc.)
**Use Prompt Templates when:**
- You need precise control over prompt structure
- You have complex custom requirements
- You want to reuse specific prompt patterns across scenes
## The Build Prompt Node
![Build Prompt Example](../img/build_prompt.png)
**Expected output from the example above:**
A fully assembled prompt with:
- Base template structure from `common.base`
- Director agent context
- Dynamic instructions: "Don't over-analyze"
- Scene context with memory, intent, and extra context
- Question: "Answer this question: Is there a tiger in the room?"
### Inputs
- **`state`**: The graph state (required)
- **`agent`**: The agent that will receive the prompt (required)
- **`instructions`** (optional): Text instructions to include in the prompt
- **`dynamic_context`** (optional): List of `DynamicInstruction` objects for context
- **`dynamic_instructions`** (optional): List of `DynamicInstruction` objects for instructions
- **`memory_prompt`** (optional): Semantic query for memory retrieval
### Outputs
- **`state`**: Passthrough of the input state
- **`agent`**: Passthrough of the input agent
- **`prompt`**: The constructed `Prompt` object
- **`rendered`**: The rendered prompt as a string
- **`response_length`**: The calculated response length for token budgeting
### Properties
#### Template Configuration
- **`template_file`** (default: `"base"`): The template file to use
- **`scope`** (default: `"common"`): The template scope (common, agent-specific, etc.)
!!! warning "Template Compatibility"
The Build Prompt node requires templates specifically designed to work with its configuration options. The default `common/base.jinja2` template is pre-configured to respect all the `include_*` boolean properties and dynamic instruction inputs.
If you change the `template_file` or `scope`, ensure the template is compatible with Build Prompt's variable structure, or the context control properties may not work as expected.
#### Context Control
- **`include_scene_intent`** (default: `true`): Include the scene's current intent/direction
- **`include_extra_context`** (default: `true`): Include pins, reinforcements, and content classification
- **`include_memory_context`** (default: `true`): Include relevant memories from the scene via RAG (Retrieval-Augmented Generation). Works best when `memory_prompt` is provided to guide semantic search
- **`include_scene_context`** (default: `true`): Include scene history and state
- **`include_character_context`** (default: `false`): Include active character details
- **`include_gamestate_context`** (default: `false`): Include game state variables
#### Advanced Settings
- **`reserved_tokens`** (default: `312`): Tokens reserved from the context budget before calculating how much scene history to include. This provides a buffer for the response and any template overhead (range: 16-1024)
- **`limit_max_tokens`** (default: `0`): Maximum token limit (0 = use client context limit)
- **`response_length`** (default: `0`): Expected length of the response
- **`technical`** (default: `false`): Include technical context (IDs, typing information)
- **`dedupe_enabled`** (default: `true`): Enable deduplication in the prompt
- **`memory_prompt`** (default: `""`): Semantic query string for memory retrieval. Provide this to guide what memories are retrieved when `include_memory_context` is enabled
- **`prefill_prompt`** (default: `""`): Text to prefill the response
- **`return_prefill_prompt`** (default: `false`): Return the prefill with response
## Dynamic Instructions
Dynamic instructions allow you to inject contextual information into prompts at runtime. They come in two types:
### Dynamic Context
Provides background information and context to the agent. Use the **Dynamic Instruction** node connected to the `dynamic_context` input (typically via a List Collector).
### Dynamic Instructions
Provides specific instructions or directives to the agent. Use the **Dynamic Instruction** node connected to the `dynamic_instructions` input (typically via a List Collector).
**Dynamic Instruction Node Properties:**
- **`header`**: The instruction header/title
- **`content`**: The instruction content/body
## Example Workflow
The example screenshot shows a typical workflow:
1. **Agent Selection**: Get the `director` agent
2. **Dynamic Instructions**: Create a "Don't over-analyze" instruction using the Dynamic Instruction node
3. **Collect Instructions**: Use a List Collector to gather dynamic instructions
4. **Instructions**: Provide the main instruction via Make Text node: "Answer this question: Is there a tiger in the room?"
5. **Build Prompt**: Configure context needs (scene intent, extra context, memory, scene context enabled)
6. **Generate Response**: Send the built prompt to the agent with appropriate settings
## Common Patterns
### Simple Question Prompt
```
[Get Agent] → [Build Prompt] → [Generate Response]
[Make Text: "Your question here"]
```
### Prompt with Dynamic Instructions
```
[Dynamic Instruction] → [List Collector] → [Build Prompt] → [Generate Response]
[Get Agent] ────────────────────────────────────↑
[Make Text: "Main instruction"] ────────────────↑
```
### Analysis with Full Context
Enable all context options:
- `include_scene_intent`: true
- `include_extra_context`: true
- `include_memory_context`: true
- `include_scene_context`: true
- `include_character_context`: true
- `include_gamestate_context`: true
### Quick Direction with Minimal Context
Disable unnecessary context:
- `include_character_context`: false
- `include_gamestate_context`: false
- `include_memory_context`: false (if not needed)
## Token Budget Management
Build Prompt automatically manages token budgets for scene history inclusion:
1. **Start with max context**: Uses `max_tokens` from the agent's client
2. **Subtract reserved tokens**: Removes `reserved_tokens` to create a buffer for the response
3. **Count rendered context**: Calculates tokens used by all enabled contexts (intent, memory, instructions, etc.)
4. **Calculate scene history budget**: `budget = max_tokens - reserved_tokens - count_tokens(rendered_contexts)`
5. **Fill with scene history**: Includes as much scene history as fits in the remaining budget
The `reserved_tokens` setting (default: 312) ensures there's always space reserved for the agent's response and prevents the context from being completely filled. Increase it if responses are getting cut off; decrease it if you want more scene history included.
## How Build Prompt Works with Templates
The Build Prompt node works by passing all its configuration options as variables to the template. The default `common/base.jinja2` template is specifically structured to:
1. **Check boolean flags**: Uses `{% if include_scene_intent %}` to conditionally include context sections
2. **Include sub-templates**: Dynamically includes templates like `scene-intent.jinja2`, `memory-context.jinja2`, etc.
3. **Process dynamic instructions**: Renders both `dynamic_context` and `dynamic_instructions` lists
4. **Calculate token budgets**: Uses `count_tokens()` to budget space for scene history
5. **Apply prefill prompts**: Handles the `prefill_prompt` and `return_prefill_prompt` options
This is why changing the template requires ensuring compatibility - a different template must expect and use these same variables.
## Template Scopes
The `scope` property determines where templates are loaded from:
- **`common`**: Shared templates in `templates/prompts/common/`
- **Agent types**: Agent-specific templates in `templates/prompts/{agent_type}/`
- `narrator`, `director`, `creator`, `editor`, `summarizer`, `world_state`
The `template_file` property references the template name without the `.jinja2` extension.

View File

@@ -4,25 +4,31 @@
The node editor is available in the main scene window once the scene is switched to creative mode.
Switch to creative mode through the creative mode toggle in the scene toolbar.
Open the node editor by clicking the :material-chart-timeline-variant-shimmer: icon in the main toolbar (upper left).
![Switch to creative mode](../img/toggle-node-editor.png)
![Switch to creative mode](../img/open-node-editor.png)
Exit the node editor the same way by clicking the :material-exit-to-app: icon in the main toolbar (upper left).
![Exit node editor](../img/close-node-editor.png)
## Module Library
![Module Library](../img/user-interface-0001.png)
The **:material-group: Modules** Library can be found at the bottom of the editor.
The **:material-file-tree: Modules** Library can be found at the left sidebar of the editor. If the sidebar is closed, click the :material-file-tree: icon in the main toolbar (upper left) to open it.
It holds all the node modules that talemate has currently installed and is the main way to add new modules to the editor or open existing modules for inspection or editing.
### Module listing
Node modules come in three categories:
Node modules are organized into hierarchical groups:
- Scene level modules: Purple, these modules live with scene project
- Installed modules: Brown, these are the modules installed through the `templates/modules` directory
- Core modules: Grey, these are the modules that are part of the core talemate installation
- **scene**: Scene-level modules that live with your project
- **agents/{agent}**: Agent-specific modules organized by agent name
- **core**: Core talemate system modules
- **installed/{project}**: Installed modules grouped by project (from `templates/modules/{project}`)
- **templates**: General template modules
All modules can be opened and inspected, but **only scene level modules can be edited**.
@@ -62,6 +68,9 @@ Select the appropriate module type.
| :material-function: Function | Creates a new [function](functions.md) module |
| :material-file: Module | Creates a new module |
| :material-source-branch-sync: Scene Loop | Creates a new scene loop module |
| :material-package-variant: Package | Creates a new package module |
| :material-chat: Director Chat Action | Creates a new director chat action module |
| :material-robot-happy: Agent Websocket Handler | Creates a new agent websocket handler module |
In the upcoming dialog you can name the new module and set the registry path.
@@ -226,6 +235,20 @@ To paste a node, select the location where you want to paste it and hit `Ctrl+V`
You can also hold the `Alt` key and drag the selected node(s) to duplicate them and drag the duplicate to the desired location.
##### Alt+Shift drag to create counterpart
Certain nodes support creating a "counterpart" node. Hold `Alt+Shift` and drag the node to create its paired counterpart node.
For example:
- **Set State → Get State**: Creates a Get State node with matching scope and variable name
- **Input → Output**: Creates the corresponding socket node with matching configuration
The counterpart node is positioned near the original and can be immediately dragged to the desired location.
!!! note "Limited node support"
This feature is currently only available for specific node types like Get/Set State and Input/Output socket nodes.
#### Node Properties
Most nodes come with properties that can be edited. To edit a node property, click on the corresponding input widget in the node.

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -0,0 +1,34 @@
# Restoring Scenes from Backups
Talemate maintains automatic backup revisions of your scenes. You can restore any scene to a previous state from the Quick Load screen.
## How to restore a scene
1. From the main screen, locate your scene in the **Quick load** section
2. Click the three-dot menu (⋮) on the scene card
3. Select **Restore from Backup**
![Restore menu option](/talemate/img/0.33.0/restore-from-backup.png)
## Restore options
![Restore menu option](/talemate/img/0.33.0/restore-from-backup-dlg.png)
The backup restore dialog provides several restoration options:
- **Restore Earliest** - Returns the scene to its initial state (revision 0)
- **Restore Latest** - Restores the most recent saved state
- **Filter by date/time** - Find and restore to a specific point in time
When you use the date/time filter, Talemate will show the closest available revision to your selected time.
## Important notes
!!! warning
Restoring creates a **new, unsaved scene** from the selected revision. Your original scene file will **not** be modified. This allows you to safely explore previous states without losing your current progress.
After restoration:
- The restored scene opens as a new, unsaved scene
- You must manually save it to preserve the restored state
- The original scene file remains unchanged in its current state

View File

@@ -2,4 +2,5 @@ nav:
- Outline: outline.md
- Direction: direction.md
- Settings: settings.md
- Shared Context: shared-context.md
- Export: export.md

View File

@@ -0,0 +1,125 @@
# Shared Context
Shared Context allows you to share specific characters, world entries, and history across multiple scenes within the same project. This is useful for creating interconnected stories where certain elements remain consistent across different scenarios.
## Accessing Shared Context
Navigate to **:material-earth-box: World Editor** :material-arrow-right: **:material-script: Scene** :material-arrow-right: **:material-earth: Shared Context**
![Shared Context - No link](/talemate/img/0.33.0/shared-context-1.png)
## Creating a Shared Context
1. Click the **New** button
2. Enter a filename for your shared context
3. The file will be saved as a `.json` file in the scene's `shared-context` folder
## Linking a Scene to Shared Context
1. Select a shared context file from the **Available** list by checking its checkbox
2. Only one shared context can be active per scene
3. To unlink, uncheck the selected shared context
When a scene is linked to a shared context, you'll see:
- Number of shared characters
- Number of shared world entries
- A **New scene** button for creating additional scenes with the same context
![Shared Context - Linked](/talemate/img/0.33.0/shared-context-2.png)
## Creating New Scenes with Shared Context
Once a scene is linked to a shared context, you can create new scenes that inherit the same shared elements:
1. Click the **New scene** button
2. Optionally provide instructions for generating a new premise
3. Select which shared characters to activate in the new scene
4. Click **Create and load**
![Create New Scene dialog](/talemate/img/0.33.0/shared-context-new-scene.png)
The new scene will:
- Be linked to the same shared context
- Inherit the content classification settings
- Use the same agent persona templates
- Use the same writing style template
- Include selected shared characters
- Be part of the same project
!!! warning
If the current scene is not saved, any unsaved changes will be lost when creating a new scene.
## Managing Shared Context Files
- **Refresh** - Updates the list of available shared context files
- **Delete** - Removes a shared context file (use the inline delete button next to each item)
## Marking Elements as Shared
Once a scene is linked to a shared context, you can mark specific elements to be shared across all scenes using that context.
### Sharing Characters
1. Navigate to **:material-earth-box: World Editor** :material-arrow-right: **:material-account-multiple: Characters**
2. Select a character from the list
3. At the bottom of the character editor, check the **Shared to World Context** checkbox
![Shared to World Context checkbox](/talemate/img/0.33.0/shared-context-3.png)
When shared, the character card will highlight in orange/amber to indicate its shared status.
#### Sharing Individual Attributes and Details
Once a character is marked as shared, you can control which specific attributes and details are shared:
**For Attributes:**
1. Open the character and go to the **Attributes** tab
2. Select an attribute from the list
3. Click ![Share with world](/talemate/img/0.33.0/share-with-world.png) to add it to the shared context
4. Shared attributes are marked with a :material-earth: icon in the list
5. Click ![Unshare from world](/talemate/img/0.33.0/unshare-from-world.png) to remove it from sharing
**For Details:**
1. Open the character and go to the **Details** tab
2. Select a detail from the list
3. Click ![Share with world](/talemate/img/0.33.0/share-with-world.png) to add it to the shared context
4. Shared details are marked with a :material-earth: icon in the list
5. Click ![Unshare from world](/talemate/img/0.33.0/unshare-from-world.png) to remove it from sharing
This allows you to selectively share only relevant character information across scenes while keeping other aspects scene-specific.
### Sharing World Entries
1. Navigate to **:material-earth-box: World Editor** :material-arrow-right: **:material-earth: World**
2. Select or create a world entry
3. Check the **Shared to World Context** checkbox in the entry editor
![World Entry Shared to World Context](/talemate/img/0.33.0/world-entry-shared-context.png)
Shared world entries appear with an orange/amber highlight. These entries contain locations, lore, and world-building information that will be accessible across all linked scenes.
### Sharing History
1. Navigate to **:material-earth-box: World Editor** :material-arrow-right: **:material-history: History**
2. If the sidebar isn't visible, click the :material-arrow-collapse-left: icon in the upper left to open it
3. Under **Shared world context**, check **Share static history**
![History Shared Context](/talemate/img/0.33.0/history-shared-context.png)
!!! info "Static History Only"
Only **static history entries** (manually created base entries) can be shared. Summarized history layers cannot be shared directly.
!!! tip "Sharing Summarized Content"
To share summarized scene progression, use the **Summarize to World Entry** button in the History tools menu. This creates a world entry from your scene's progress that can then be marked as shared.
## What Gets Shared
- **Characters** - Complete character definitions, personalities, attributes, and details
- **World Entries** - Locations, lore, and world-building information
- **Static History** - Manually created history entries (not summarized layers)
These elements remain synchronized across all scenes linked to the same shared context.

View File

@@ -1,6 +1,6 @@
[project]
name = "talemate"
version = "0.32.3"
version = "0.33.0"
description = "AI-backed roleplay and narrative tools"
authors = [{name = "VeguAITools"}]
license = {text = "GNU Affero General Public License v3.0"}
@@ -65,6 +65,7 @@ dependencies = [
"soundfile>=0.13.1",
# F5-TTS
"f5-tts>=1.1.7",
"deepdiff>=8.6.1",
]
[project.optional-dependencies]
@@ -137,4 +138,4 @@ torchaudio = [
[[tool.uv.index]]
name = "pytorch-cu128"
url = "https://download.pytorch.org/whl/cu128"
explicit = true
explicit = true

View File

@@ -31,9 +31,12 @@
"ts": "P12M"
}
],
"character_states": {},
"characters": [
{
"active_characters": [
"Elmer",
"Kaira"
],
"character_data": {
"Elmer": {
"name": "Elmer",
"description": "Elmer is a seasoned space explorer, having traversed the cosmos for over three decades. At thirty-eight years old, his muscular frame still cuts an imposing figure, clad in a form-fitting black spacesuit adorned with intricate silver markings. As the captain of his own ship, he wields authority with confidence yet never comes across as arrogant or dictatorial. Underneath this tough exterior lies a man who genuinely cares for his crew and their wellbeing, striking a balance between discipline and compassion.",
"greeting_text": "",
@@ -57,7 +60,7 @@
"is_player": true,
"cover_image": null
},
{
"Kaira": {
"name": "Kaira",
"description": "Kaira is a meticulous and dedicated Altrusian woman who serves as second-in-command aboard their tiny exploration vessel. As a native of the planet Altrusia, she possesses striking features unique among her kind; deep violet skin adorned with intricate patterns resembling stardust, large sapphire eyes, lustrous glowing hair cascading down her back, and standing tall at just over six feet. Her form fitting bodysuit matches her own hue, giving off an ethereal presence. With her innate grace and precision, she moves efficiently throughout the cramped confines of their ship. A loyal companion to Captain Elmer Farstield, she approaches every task with diligence and focus while respecting authority yet challenging decisions when needed. Dedicated to maintaining order within their tight quarters, Kaira wields several advanced technological devices including a multi-tool, portable scanner, high-tech communications system, and personal shield generator - all essential for navigating unknown territories and protecting themselves from harm. In this perilous universe full of mysteries waiting to be discovered, Kaira stands steadfast alongside her captain \u2013 ready to embrace whatever challenges lie ahead in their quest for knowledge beyond Earth's boundaries.",
"greeting_text": "",
@@ -100,7 +103,7 @@
"is_player": false,
"cover_image": null
}
],
},
"immutable_save": true,
"goal": null,
"goals": [],

View File

@@ -333,8 +333,7 @@
"entry_id": "sim.quarantined",
"text": null,
"meta": {},
"create_pin": true,
"id": "sim.quarantined"
"create_pin": true
},
"x": 300,
"y": 1030,

View File

@@ -7,16 +7,18 @@
"environment": "scene",
"archived_history": [],
"layered_history": [],
"characters": [
{
"active_characters": [
"User"
],
"character_data": {
"User": {
"name": "User",
"gender": "unknown",
"color": "cornflowerblue",
"base_attributes": {},
"is_player": true
}
],
"inactive_characters": {},
},
"context": "a holodeck like experience",
"world_state": {
"characters": {},

View File

@@ -4,12 +4,14 @@ import asyncio
import dataclasses
from inspect import signature
import re
import traceback
from abc import ABC
from functools import wraps
from typing import Callable, Union
import uuid
import pydantic
import structlog
from typing import TYPE_CHECKING
import talemate.emit.async_signals
import talemate.instance as instance
@@ -24,6 +26,12 @@ import talemate.config.schema as config_schema
from talemate.client.context import (
ClientContext,
)
from talemate.game.engine.nodes.core import GraphState
from talemate.game.engine.nodes.registry import get_nodes_by_base_type, get_node
from talemate.game.engine.nodes.run import FunctionWrapper
if TYPE_CHECKING:
from talemate.tale_mate import Scene
__all__ = [
"Agent",
@@ -102,6 +110,9 @@ class DynamicInstruction(pydantic.BaseModel):
content: str
def __str__(self) -> str:
if not self.content:
return ""
return "\n".join(
[f"<|SECTION:{self.title}|>", self.content, "<|CLOSE_SECTION|>"]
)
@@ -232,6 +243,52 @@ class Agent(ABC):
return actions
@classmethod
def config_options(cls, agent=None):
config_options = {
"client": [name for name, _ in instance.client_instances()],
"enabled": agent.enabled if agent else True,
"has_toggle": agent.has_toggle if agent else False,
"experimental": agent.experimental if agent else False,
"requires_llm_client": cls.requires_llm_client,
}
actions = getattr(agent, "actions", None)
if actions:
config_options["actions"] = {k: v.model_dump() for k, v in actions.items()}
else:
config_options["actions"] = {}
return config_options
@classmethod
async def init_nodes(cls, scene: "Scene", state: GraphState):
log.debug(f"{cls.agent_type}.init_nodes")
if not cls.websocket_handler:
return
cls.websocket_handler.clear_sub_handlers()
for node_cls in get_nodes_by_base_type("agents/AgentWebsocketHandler"):
_node = node_cls()
handler_name = _node.get_property("name")
agent_type = _node.get_property("agent")
if agent_type != cls.agent_type:
continue
async def handler_fn(router, data: dict):
state: GraphState = scene.nodegraph_state
node = get_node(_node.registry)()
fn = FunctionWrapper(node, node, state)
await fn(websocket_router=router, data=data)
cls.websocket_handler.register_sub_handler(handler_name, handler_fn)
log.debug(
f"{cls.agent_type}.init_nodes.websocket_handler",
handler_name=handler_name,
)
@property
def config(self) -> Config:
return get_config()
@@ -300,24 +357,6 @@ class Agent(ABC):
# is experimental should override this property
return False
@classmethod
def config_options(cls, agent=None):
config_options = {
"client": [name for name, _ in instance.client_instances()],
"enabled": agent.enabled if agent else True,
"has_toggle": agent.has_toggle if agent else False,
"experimental": agent.experimental if agent else False,
"requires_llm_client": cls.requires_llm_client,
}
actions = getattr(agent, "actions", None)
if actions:
config_options["actions"] = {k: v.model_dump() for k, v in actions.items()}
else:
config_options["actions"] = {}
return config_options
@property
def meta(self):
return {
@@ -554,10 +593,15 @@ class Agent(ABC):
return
if fut.exception():
exc = fut.exception()
tb = "".join(
traceback.format_exception(type(exc), exc, exc.__traceback__)
)
log.error(
"background processing error",
agent=self.agent_type,
exc=fut.exception(),
exc=exc,
traceback=tb,
)
if error_handler:

View File

@@ -107,9 +107,9 @@ class ConversationAgent(MemoryRAGMixin, Agent):
type="number",
label="Generation Length (tokens)",
description="Maximum number of tokens to generate for a conversation response.",
value=128,
value=192,
min=32,
max=512,
max=4096,
step=32,
),
"jiggle": AgentActionConfig(

View File

@@ -42,8 +42,11 @@ class GenerateConversation(AgentNode):
self.set_property("trigger_conversation_generated", True)
self.add_output("state")
self.add_output("generated", socket_type="str")
self.add_output("message", socket_type="message_object")
self.add_output("character", socket_type="character")
self.add_output("instruction", socket_type="str")
async def run(self, state: GraphState):
character: "Character" = self.get_input_value("character")
@@ -72,4 +75,12 @@ class GenerateConversation(AgentNode):
message = messages[0]
self.set_output_values({"generated": message.message, "message": message})
self.set_output_values(
{
"generated": message.message,
"message": message,
"character": character,
"instruction": instruction,
"state": self.get_input_value("state"),
}
)

View File

@@ -65,7 +65,7 @@ class ConversationWebsocketHandler(Plugin):
meta={"character": character.name},
)
emit("director", message=director_message, character=character)
self.scene.push_history(director_message)
await self.scene.push_history(director_message)
generated_messages = await self.agent.converse(
actor, emit_signals=payload.emit_signals
)
@@ -77,5 +77,5 @@ class ConversationWebsocketHandler(Plugin):
)
for message in generated_messages:
self.scene.push_history(message)
await self.scene.push_history(message)
emit("character", message=message, character=character)

View File

@@ -1,10 +1,10 @@
import json
import re
import random
import uuid
from typing import TYPE_CHECKING, Tuple
import dataclasses
import traceback
import uuid
import pydantic
import structlog
@@ -21,6 +21,9 @@ from talemate.world_state.templates import (
Spices,
WritingStyle,
)
from talemate.changelog import write_reconstructed_scene
from talemate.save import SceneEncoder
import os
from talemate.agents.base import AgentAction, AgentActionConfig, AgentTemplateEmission
import talemate.emit.async_signals as async_signals
@@ -237,6 +240,9 @@ class AssistantMixin:
Request content from the assistant.
"""
if not writing_style:
writing_style = self.scene.writing_style
generation_options = GenerationOptions(
spices=spices,
spice_level=spice_level,
@@ -354,6 +360,9 @@ class AssistantMixin:
)
return emission.response
if content.lower().startswith(context_name + ": "):
content = content[len(context_name) + 2 :]
emission.response = content.strip().strip("*").strip()
await async_signals.get("agent.creator.contextual_generate.after").send(
@@ -368,6 +377,7 @@ class AssistantMixin:
attribute_name: str,
instructions: str = "",
original: str | None = None,
length: int = 192,
generation_options: GenerationOptions = None,
) -> str:
"""
@@ -381,6 +391,7 @@ class AssistantMixin:
character=character.name,
instructions=instructions,
original=original,
length=length,
**generation_options.model_dump(),
)
@@ -410,6 +421,33 @@ class AssistantMixin:
**generation_options.model_dump(),
)
@set_processing
async def generate_scene_title(
self,
instructions: str = "",
length: int = 20,
generation_options: GenerationOptions = None,
) -> str:
"""
Wrapper for contextual_generate that generates a scene title.
"""
if not generation_options:
generation_options = GenerationOptions()
title = await self.contextual_generate_from_args(
context="scene title:scene title",
instructions=instructions,
length=length,
**generation_options.model_dump(),
)
# replace special characters
title = re.sub(r"[^a-zA-Z0-9\s-]", "", title)
if title.lower().startswith("scene title "):
title = title[11:]
return title.split("\n")[0].strip()
@set_processing
async def generate_thematic_list(
self,
@@ -479,12 +517,13 @@ class AssistantMixin:
except IndexError:
pass
if input.strip().endswith('"'):
prefix = " *"
elif input.strip().endswith("*"):
prefix = ' "'
else:
prefix = ""
outvar = {
"tag_name": "CONTINUE",
}
def set_tag_name(tag_name: str) -> str:
outvar["tag_name"] = tag_name
return tag_name
template_vars = {
"scene": self.scene,
@@ -497,7 +536,7 @@ class AssistantMixin:
"message": message,
"anchor": anchor,
"non_anchor": non_anchor,
"prefix": prefix,
"set_tag_name": set_tag_name,
}
emission = AutocompleteEmission(
@@ -521,13 +560,19 @@ class AssistantMixin:
dedupe_enabled=False,
)
# attempt to extract the continuation from the response
try:
tag_name = outvar["tag_name"]
response = (
response.split(f"<{tag_name}>")[1].split(f"</{tag_name}>")[0].strip()
)
except IndexError:
pass
response = (
response.replace("...", "").lstrip("").rstrip().replace("END-OF-LINE", "")
)
if prefix:
response = prefix + response
emission.response = response
await async_signals.get("agent.creator.autocomplete.after").send(emission)
@@ -574,6 +619,14 @@ class AssistantMixin:
input=input,
)
outvar = {
"tag_name": "CONTINUE",
}
def set_tag_name(tag_name: str) -> str:
outvar["tag_name"] = tag_name
return tag_name
template_vars = {
"scene": self.scene,
"max_tokens": self.client.max_token_length,
@@ -582,6 +635,7 @@ class AssistantMixin:
"response_length": response_length,
"anchor": anchor,
"non_anchor": non_anchor,
"set_tag_name": set_tag_name,
}
emission = AutocompleteEmission(
@@ -603,6 +657,16 @@ class AssistantMixin:
pad_prepended_response=False,
dedupe_enabled=False,
)
# attempt to extract the continuation from the response
try:
tag_name = outvar["tag_name"]
response = (
response.split(f"<{tag_name}>")[1].split(f"</{tag_name}>")[0].strip()
)
except IndexError:
pass
response = response.strip().replace("...", "").strip()
if response.startswith(input):
@@ -628,77 +692,110 @@ class AssistantMixin:
save_name: str | None = None,
):
"""
Allows to fork a new scene from a specific message
in the current scene.
Creates a new scene forked from a specific message.
All content after the message will be removed and the
context database will be re imported ensuring a clean state.
All state reinforcements will be reset to their most recent
state before the message.
This properly creates a new scene file without modifying the current scene,
then signals the frontend to load the new scene.
"""
emit("status", "Creating scene fork ...", status="busy")
try:
emit("status", "Preparing to fork scene...", status="busy")
if not save_name:
# build a save name
uuid_str = str(uuid.uuid4())[:8]
save_name = f"{uuid_str}-forked"
save_name = self.scene.generate_name()
log.info("Forking scene", message_id=message_id, save_name=save_name)
world_state = get_agent("world_state")
# does a message with the given id exist?
index = self.scene.message_index(message_id)
if index is None:
# Find the message to fork from
message = self.scene.get_message(message_id)
if not message:
raise ValueError(f"Message with id {message_id} not found.")
# truncate scene.history keeping index as the last element
self.scene.history = self.scene.history[: index + 1]
# Determine fork type based on message revision
use_reconstructive_fork = message.rev > 0
# truncate scene.archived_history keeping the element where `end` is < `index`
# as the last element
self.scene.archived_history = [
x
for x in self.scene.archived_history
if "end" not in x or x["end"] < index
]
if use_reconstructive_fork:
log.info(
"Creating reconstructive fork",
message_id=message_id,
rev=message.rev,
)
emit("status", "Creating reconstructive fork...", status="busy")
# the same needs to be done for layered history
# where each layer is truncated based on what's left in the previous layer
# using similar logic as above (checking `end` vs `index`)
# layer 0 checks archived_history
# Create fork file with reconstructed scene data (shared_context will be disconnected)
fork_file_path = await write_reconstructed_scene(
self.scene,
message.rev,
f"{save_name}.json",
overrides={
"immutable_save": False,
"memory_id": str(uuid.uuid4())[:10],
},
)
new_layered_history = []
for layer_number, layer in enumerate(self.scene.layered_history):
if layer_number == 0:
index = len(self.scene.archived_history) - 1
else:
index = len(new_layered_history[layer_number - 1]) - 1
log.info(
"Reconstructive fork created",
save_name=save_name,
rev=message.rev,
path=fork_file_path,
)
else:
log.info("Creating shallow fork", message_id=message_id)
emit("status", "Creating shallow fork...", status="busy")
new_layer = [x for x in layer if x["end"] < index]
new_layered_history.append(new_layer)
# Create a copy of current scene data
scene_data = self.scene.serialize
self.scene.layered_history = new_layered_history
scene_data["immutable_save"] = False
scene_data["memory_id"] = str(uuid.uuid4())[:10]
# save the scene
await self.scene.save(copy_name=save_name)
# Truncate history to the fork point
index = self.scene.message_index(message_id)
if index is None:
raise ValueError(f"Message with id {message_id} not found.")
log.info("Scene forked", save_name=save_name)
# Truncate history (keeping index as the last element)
scene_data["history"] = self.scene.history[: index + 1]
# re-emit history
await self.scene.emit_history()
# Truncate archived_history (keeping elements where 'end' < index)
scene_data["archived_history"] = [
x
for x in self.scene.archived_history
if "end" not in x or x["end"] < index
]
emit("status", "Updating world state ...", status="busy")
# Truncate layered history (same logic as original)
new_layered_history = []
for layer_number, layer in enumerate(self.scene.layered_history):
if layer_number == 0:
layer_index = len(scene_data["archived_history"]) - 1
else:
layer_index = len(new_layered_history[layer_number - 1]) - 1
# reset state reinforcements
await world_state.update_reinforcements(force=True, reset=True)
new_layer = [x for x in layer if x["end"] < layer_index]
new_layered_history.append(new_layer)
# update world state
await self.scene.world_state.request_update()
scene_data["layered_history"] = new_layered_history
# Clear shared_context for fork (same logic as reconstructive fork)
if scene_data.get("shared_context"):
log.info(
"Disconnecting forked scene from shared_context",
shared_context=scene_data.get("shared_context"),
)
scene_data["shared_context"] = ""
# Write the fork file
fork_file_path = os.path.join(self.scene.save_dir, f"{save_name}.json")
with open(fork_file_path, "w") as f:
json.dump(scene_data, f, indent=2, cls=SceneEncoder)
log.info(
"Shallow fork created", save_name=save_name, path=fork_file_path
)
emit("status", "Scene forked successfully", status="success")
# Return the fork file path so the websocket handler can load it
return fork_file_path
emit("status", "Scene forked", status="success")
except Exception:
log.error("Scene fork failed", exc=traceback.format_exc())
emit("status", "Scene fork failed", status="error")

View File

@@ -37,6 +37,7 @@ class CharacterCreatorMixin:
character: Character,
instructions: str = "",
information: str = "",
update_existing: bool = False,
):
instructions = await Prompt.request(
"creator.determine-character-dialogue-instructions",
@@ -48,6 +49,7 @@ class CharacterCreatorMixin:
"max_tokens": self.client.max_token_length,
"instructions": instructions,
"information": information,
"update_existing": update_existing,
},
)

View File

@@ -5,6 +5,7 @@ from talemate.game.engine.nodes.core import (
GraphState,
PropertyField,
UNRESOLVED,
InputValueError,
)
from talemate.game.engine.nodes.registry import register
from talemate.game.engine.nodes.agent import AgentSettingsNode, AgentNode
@@ -115,6 +116,12 @@ class DetermineCharacterDialogueInstructions(AgentNode):
type="text",
default="",
)
update_existing = PropertyField(
name="update_existing",
description="Whether to update the existing dialogue instructions",
type="bool",
default=False,
)
def __init__(self, title="Determine Character Dialogue Instructions", **kwargs):
super().__init__(title=title, **kwargs)
@@ -123,22 +130,34 @@ class DetermineCharacterDialogueInstructions(AgentNode):
self.add_input("state")
self.add_input("character", socket_type="character")
self.add_input("instructions", socket_type="str", optional=True)
self.add_input("update_existing", socket_type="bool", optional=True)
self.set_property("instructions", "")
self.set_property("update_existing", False)
self.add_output("state", socket_type="any")
self.add_output("character", socket_type="character")
self.add_output("dialogue_instructions", socket_type="str")
self.add_output("original", socket_type="str")
async def run(self, state: GraphState):
character = self.require_input("character")
instructions = self.normalized_input_value("instructions")
instructions: str | None = self.normalized_input_value("instructions")
update_existing: bool | None = self.normalized_input_value("update_existing")
original: str | None = character.dialogue_instructions or ""
dialogue_instructions = (
await self.agent.determine_character_dialogue_instructions(
character, instructions
character, instructions, update_existing=update_existing
)
)
self.set_output_values({"dialogue_instructions": dialogue_instructions})
self.set_output_values(
{
"state": state,
"character": character,
"dialogue_instructions": dialogue_instructions,
"original": original,
}
)
@register("agents/creator/ContextualGenerate")
@@ -195,6 +214,7 @@ class ContextualGenerate(AgentNode):
"general",
"list",
"scene",
"static history",
"world context",
],
default="general",
@@ -270,6 +290,11 @@ class ContextualGenerate(AgentNode):
self.add_output("state")
self.add_output("text", socket_type="str")
self.add_output("character", socket_type="character")
self.add_output("context_type", socket_type="str")
self.add_output("context_name", socket_type="str")
self.add_output("instructions", socket_type="str")
self.add_output("original", socket_type="str")
async def run(self, state: GraphState):
scene = active_scene.get()
@@ -285,7 +310,10 @@ class ContextualGenerate(AgentNode):
context_aware = self.normalized_input_value("context_aware")
history_aware = self.normalized_input_value("history_aware")
context = f"{context_type}:{context_name}" if context_name else context_type
if not context_name:
raise InputValueError(self, "context_name", "Context name is not set")
context = f"{context_type}:{context_name}"
if isinstance(character, scene.Character):
character = character.name
@@ -307,7 +335,17 @@ class ContextualGenerate(AgentNode):
history_aware=history_aware,
)
self.set_output_values({"state": state, "text": text})
self.set_output_values(
{
"state": state,
"text": text,
"character": scene.get_character(character),
"context_type": context_type,
"context_name": context_name,
"instructions": instructions,
"original": original,
}
)
@register("agents/creator/GenerateThematicList")

View File

@@ -1,5 +1,7 @@
from __future__ import annotations
from typing import TYPE_CHECKING
import structlog
from talemate.emit import emit
@@ -10,20 +12,25 @@ from talemate.agents.registry import register
from talemate.agents.memory.rag import MemoryRAGMixin
from talemate.client import ClientBase
from talemate.game.focal.schema import Call
from talemate.game.engine.nodes.core import GraphState
from .guide import GuideSceneMixin
from .generate_choices import GenerateChoicesMixin
from .legacy_scene_instructions import LegacySceneInstructionsMixin
from .auto_direct import AutoDirectMixin
from .websocket_handler import DirectorWebsocketHandler
from .chat.mixin import DirectorChatMixin
from .character_management import CharacterManagementMixin
import talemate.agents.director.nodes # noqa: F401
if TYPE_CHECKING:
from talemate.tale_mate import Scene
log = structlog.get_logger("talemate.agent.director")
@register()
class DirectorAgent(
DirectorChatMixin,
GuideSceneMixin,
MemoryRAGMixin,
GenerateChoicesMixin,
@@ -69,8 +76,14 @@ class DirectorAgent(
GuideSceneMixin.add_actions(actions)
AutoDirectMixin.add_actions(actions)
CharacterManagementMixin.add_actions(actions)
DirectorChatMixin.add_actions(actions)
return actions
@classmethod
async def init_nodes(cls, scene: "Scene", state: GraphState):
await super(DirectorAgent, cls).init_nodes(scene, state)
await DirectorChatMixin.chat_init_nodes(scene, state)
def __init__(self, client: ClientBase | None = None, **kwargs):
self.is_enabled = True
self.client = client
@@ -112,7 +125,7 @@ class DirectorAgent(
action=action,
flags=Flags.HIDDEN if console_only else Flags.NONE,
)
self.scene.push_history(message)
await self.scene.push_history(message)
emit("director", message)
def inject_prompt_paramters(

View File

@@ -5,7 +5,7 @@ import talemate.instance as instance
import talemate.agents.tts.voice_library as voice_library
from talemate.agents.tts.schema import Voice
from talemate.util import random_color
from talemate.character import deactivate_character, set_voice
from talemate.character import set_voice, activate_character
from talemate.status import LoadingStatus
from talemate.exceptions import GenerationCancelled
from talemate.agents.base import AgentAction, AgentActionConfig, set_processing
@@ -240,8 +240,8 @@ class CharacterManagementMixin:
await self.assign_voice_to_character(character)
# Deactivate the character if not active
if not active:
await deactivate_character(scene, character)
if active:
await activate_character(scene, character)
# Commit the character's details to long term memory
await character.commit_to_memory(memory)

View File

@@ -0,0 +1,51 @@
import contextvars
import pydantic
import structlog
import asyncio
from talemate.game.engine.context_id.scanner import OpenContextIDScanCollector
__all__ = [
"DirectorChatContext",
"director_chat_context",
"create_task_with_chat_context",
]
log = structlog.get_logger("talemate.agents.director.chat.context")
director_chat_context = contextvars.ContextVar("director_chat_context", default=None)
class DirectorChatContext(pydantic.BaseModel):
chat_id: str
confirm_write_actions: bool = True
token: str | None = None
_context_id_collector: OpenContextIDScanCollector | None = None
def __enter__(self):
self.token = director_chat_context.set(self)
self._context_id_collector = OpenContextIDScanCollector()
self._context_id_collector.__enter__()
return self
def __exit__(self, exc_type, exc_value, traceback):
if self._context_id_collector:
self._context_id_collector.__exit__(exc_type, exc_value, traceback)
director_chat_context.reset(self.token)
def create_task_with_chat_context(
fn,
chat_id: str,
*args,
confirm_write_actions: bool = True,
**kwargs,
):
async def wrapper(*args, **kwargs):
with DirectorChatContext(
chat_id=chat_id, confirm_write_actions=confirm_write_actions
):
return await fn(*args, **kwargs)
return asyncio.create_task(wrapper(*args, **kwargs))

View File

@@ -0,0 +1,26 @@
__all__ = [
"DirectorChatActionRejected",
"UnknownDirectorChatAction",
"InvalidDirectorChat",
]
class InvalidDirectorChat(ValueError):
def __init__(self, chat_id: str):
self.chat_id = chat_id
super().__init__(f"Invalid chat: {chat_id}")
class UnknownDirectorChatAction(ValueError):
def __init__(self, action_name: str):
self.action_name = action_name
super().__init__(f"Unknown action: {action_name}")
class DirectorChatActionRejected(IOError):
focal_reraise: bool = True
def __init__(self, action_name: str, action_description: str):
self.action_name = action_name
self.action_description = action_description
super().__init__(f"User REJECTED action: {action_name} -> {action_description}")

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,213 @@
import structlog
from typing import ClassVar
import pydantic
import asyncio
import time
from talemate.game.engine.nodes.core import (
GraphState,
PropertyField,
NodeStyle,
Node,
UNRESOLVED,
)
from talemate.game.engine.nodes.registry import register, base_node_type
from talemate.game.engine.nodes.run import Function, FunctionWrapper
from talemate.game.engine.nodes.focal import FocalArgument
from talemate.emit import emit
from talemate.context import active_scene
from .context import director_chat_context
from .exceptions import DirectorChatActionRejected
log = structlog.get_logger("talemate.game.engine.nodes.agents.director.chat")
@base_node_type("agents/director/DirectorChatAction")
class DirectorChatAction(Function):
"""
A action is a node that can be executed by the director during chat with the user
"""
_isolated: ClassVar[bool] = True
_export_definition: ClassVar[bool] = False
class Fields:
name = PropertyField(
name="name", description="The name of the action", type="str", default=""
)
description = PropertyField(
name="description",
description="The description of the action",
type="text",
default="",
)
instructions = PropertyField(
name="instructions",
description="The instructions for the action",
type="text",
default="",
)
example_json = PropertyField(
name="example_json",
description="An example JSON payload for the action",
type="text",
default=None,
)
def __init__(self, title="Command", **kwargs):
super().__init__(title=title, **kwargs)
if not self.get_property("name"):
self.set_property("name", "")
if not self.get_property("description"):
self.set_property("description", "")
async def execute_action(self, state: GraphState, **kwargs):
wrapped = FunctionWrapper(self, self, state)
await wrapped(**kwargs)
async def test_run(self, state: GraphState):
return await self.execute_action(state, **{})
@register("agents/director/chat/ActionArgument")
class DirectorChatActionArgument(FocalArgument):
"""
A argument is a node that can be used as an argument to a director chat action
"""
@pydantic.computed_field(description="Node style")
@property
def style(self) -> NodeStyle:
return NodeStyle(
node_color="#2c2a37",
title_color="#144870",
icon="F0AE7", # variable
auto_title="{name}",
)
def __init__(self, title="Director Action Argument", **kwargs):
super().__init__(title=title, **kwargs)
@register("agents/director/chat/ActionConfirm")
class DirectorChatActionConfirm(Node):
"""
If the is a chat context active that requires confirmation for write
actions, this node will block the further execution of the node graph
and send a signal to the frontend to collect the confirmation from the user (or reject the action)
"""
class Fields:
name = PropertyField(
name="name",
description="The name of the action",
type="str",
default="",
)
description = PropertyField(
name="description",
description="The description of the action",
type="text",
default="",
)
raise_on_reject = PropertyField(
name="raise_on_reject",
description="Whether to raise an error if the action is rejected",
type="bool",
default=True,
)
@pydantic.computed_field(description="Node style")
@property
def style(self) -> NodeStyle:
return NodeStyle(
# caution/confirm theme close to validation/breakpoint family
node_color="#2b273a",
title_color="#3d315b",
icon="F02D6", # help-circle-outline
auto_title="Confirm Action",
)
def __init__(self, title="Director Action Confirm", **kwargs):
super().__init__(title=title, **kwargs)
def setup(self):
self.add_input("state")
self.add_input("name", socket_type="str", optional=True)
self.add_input("description", socket_type="str", optional=True)
self.set_property("name", "")
self.set_property("description", "")
self.set_property("raise_on_reject", True)
self.add_output("accepted")
self.add_output("rejected")
self.add_output("rejected_message", socket_type="str")
async def run(self, state: GraphState):
state_value = self.get_input_value("state")
max_wait_time: int = 180
key: str = f"_director_chat_action_confirm_{self.id}"
name: str = self.normalized_input_value("name")
description: str = self.normalized_input_value("description")
raise_on_reject: bool = self.get_property("raise_on_reject")
scene = active_scene.get()
rejected_state = UNRESOLVED
try:
context = director_chat_context.get()
if context and context.confirm_write_actions:
state.shared[key] = "waiting"
start_time = time.time()
emit(
"request_action_confirmation",
data={
"chat_id": context.chat_id,
"id": self.id,
"name": name,
"description": description,
"timer": max_wait_time,
},
websocket_passthrough=True,
)
while state.shared[key] == "waiting":
if not scene.active:
log.warning(
"Director Chat Action Confirm: Scene is no longer active",
node=self.id,
)
rejected_state = state_value
break
log.debug(
"Director Chat Action Confirm: Waiting for confirmation",
node=self.id,
)
await asyncio.sleep(1)
if time.time() - start_time > max_wait_time:
log.error(
"Director Chat Action Confirm: Max wait time reached",
node=self.id,
)
rejected_state = state_value
break
if state.shared[key] == "reject":
rejected_state = state_value
if raise_on_reject and rejected_state is not UNRESOLVED:
raise DirectorChatActionRejected(name, description)
except LookupError:
pass
finally:
if key in state.shared:
del state.shared[key]
log.debug("Director Chat Action Confirm: Final output", rejected=rejected_state)
if rejected_state is not UNRESOLVED:
message = f"User REJECTED action: {name} -> {description}"
self.set_output_values(
{"rejected": rejected_state, "rejected_message": message}
)
else:
self.set_output_values({"accepted": state_value})

View File

@@ -0,0 +1,110 @@
import pydantic
from typing import Literal, Any
import uuid
__all__ = [
"DirectorChatMessage",
"DirectorChatFunctionAvailable",
"DirectorChatFunctionSelected",
"DirectorChat",
"DirectorChatActionResultMessage",
"DirectorChatBudgets",
"DirectorChatResponse",
]
class DirectorChatBudgets(pydantic.BaseModel):
"""
The budgets for the director chat
"""
max_tokens: int = 0
reserved: int = 0
scene_context_ratio: float = 0.0
def set_reserved(self, reserved: int):
self.reserved = reserved
@pydantic.computed_field(description="The number of available tokens")
@property
def available(self) -> int:
# Ensure we never return negative available tokens
remaining = self.max_tokens - self.reserved
return remaining if remaining > 0 else 0
@pydantic.computed_field(description="The number of tokens for scene context")
@property
def scene_context(self) -> int:
return int(self.scene_context_ratio * self.available)
@pydantic.computed_field(description="The number of tokens for director chat")
@property
def director_chat(self) -> int:
return int((1 - self.scene_context_ratio) * self.available)
class DirectorChatResponse(pydantic.BaseModel):
"""
A response from the director
"""
parsed_response: str
raw_response: str
budgets: DirectorChatBudgets
actions_selected: list[dict] = pydantic.Field(default_factory=list)
class DirectorChatMessage(pydantic.BaseModel):
"""
A message from the user or the director
"""
message: str
source: Literal["director", "user"]
type: Literal["text", "action_result"] = "text"
id: str = pydantic.Field(default_factory=lambda: str(uuid.uuid4())[:10])
class DirectorChatFunctionAvailable(pydantic.BaseModel):
"""
A function that is available to the director
"""
name: str
description: str
class DirectorChatFunctionSelected(pydantic.BaseModel):
"""
A function that has been selected by the director
"""
name: str
instructions: str
class DirectorChat(pydantic.BaseModel):
"""
A history of messages from the user or the director
"""
messages: list["DirectorChatMessage | DirectorChatActionResultMessage"]
id: str = pydantic.Field(default_factory=lambda: str(uuid.uuid4())[:10])
mode: Literal["normal", "decisive", "nospoilers"] = "normal"
confirm_write_actions: bool = True
class DirectorChatActionResultMessage(pydantic.BaseModel):
"""
A structured message that holds the result of an executed action.
Always originates from the director side.
"""
type: Literal["action_result"] = "action_result"
source: Literal["director"] = "director"
name: str
arguments: dict[str, Any] = pydantic.Field(default_factory=dict)
result: Any = None
instructions: str | None = None
status: Literal["success", "error", "rejected"] = "success"
id: str = pydantic.Field(default_factory=lambda: str(uuid.uuid4())[:10])

View File

@@ -0,0 +1,336 @@
import pydantic
import asyncio
import structlog
from typing import Literal, TYPE_CHECKING
from talemate.instance import get_agent
from .context import create_task_with_chat_context
import talemate.util as util
if TYPE_CHECKING:
from talemate.tale_mate import Scene
log = structlog.get_logger("talemate.server.director.chat")
class ChatHistoryPayload(pydantic.BaseModel):
chat_id: str
class ChatSendPayload(pydantic.BaseModel):
chat_id: str
message: str
class ChatClearPayload(pydantic.BaseModel):
chat_id: str
class ChatRemoveMessagePayload(pydantic.BaseModel):
chat_id: str
message_id: str
class ChatRegeneratePayload(pydantic.BaseModel):
chat_id: str
class ConfirmActionPayload(pydantic.BaseModel):
chat_id: str
id: str
decision: Literal["confirm", "reject"]
class ChatUpdateModePayload(pydantic.BaseModel):
chat_id: str
mode: Literal["normal", "decisive", "nospoilers"]
class ChatUpdateConfirmWriteActionsPayload(pydantic.BaseModel):
chat_id: str
confirm_write_actions: bool
class DirectorChatWebsocketMixin:
"""
Mixin for chat-related websocket handlers (router remains 'director').
Expects the concrete handler to provide:
- property `director` returning the DirectorAgent
- attributes `scene` and `websocket_handler` (provided by base Plugin)
"""
@property
def director(self):
return get_agent("director")
def _make_generation_callbacks(self, payload_chat_id: str):
async def _on_update(chat_id, new_messages):
try:
self.websocket_handler.queue_put(
{
"type": "director",
"action": "chat_append",
"chat_id": chat_id,
"messages": [m.model_dump() for m in new_messages],
"token_total": sum(
util.count_tokens(str(m))
for m in self.director.chat_history(chat_id)
),
}
)
except Exception as e:
log.error("director.chat.websocket.on_update.error", error=e)
async def _on_done(chat_id, budgets):
try:
self.websocket_handler.queue_put(
{
"type": "director",
"action": "chat_done",
"chat_id": chat_id,
"budgets": budgets.model_dump() if budgets else None,
}
)
except Exception as e:
log.error("director.chat.websocket.on_done.error", error=e)
async def _on_compacting(chat_id):
try:
self.websocket_handler.queue_put(
{
"type": "director",
"action": "chat_compacting",
"chat_id": chat_id,
}
)
except Exception as e:
log.error("director.chat.websocket.on_compacting.error", error=e)
async def _on_compacted(chat_id, new_messages):
try:
self.websocket_handler.queue_put(
{
"type": "director",
"action": "chat_history",
"chat_id": chat_id,
"messages": [m.model_dump() for m in new_messages],
"token_total": sum(
util.count_tokens(str(m)) for m in new_messages
),
}
)
self.websocket_handler.queue_put(
{
"type": "director",
"action": "chat_append",
"chat_id": chat_id,
"messages": [
{
"source": "director",
"type": "compaction_notice",
"message": "Older chat was summarized to keep context within limits.",
}
],
"token_delta": util.count_tokens(
"Older chat was summarized to keep context within limits."
),
}
)
except Exception as e:
log.error("director.chat.websocket.on_compacted.error", error=e)
return _on_update, _on_done, _on_compacting, _on_compacted
def _attach_task_done_callback(self, task, chat_id: str):
async def handle_task_done(task):
if task.exception():
exc = task.exception()
log.error("director.chat.websocket.task.error", error=exc)
try:
self.websocket_handler.queue_put(
{
"type": "director",
"action": "chat_done",
"chat_id": chat_id,
}
)
except Exception as e:
log.error("director.chat.websocket.task.done_emit.error", error=e)
task.add_done_callback(lambda task: asyncio.create_task(handle_task_done(task)))
async def handle_chat_create(self, data: dict):
chat = self.director.chat_create()
# emit updated list and history for the new chat
self.websocket_handler.queue_put(
{
"type": "director",
"action": "chat_created",
"chat_id": chat.id,
"chats": self.director.chat_list(),
}
)
self.websocket_handler.queue_put(
{
"type": "director",
"action": "chat_history",
"chat_id": chat.id,
"messages": [m.model_dump() for m in chat.messages],
"mode": chat.mode,
"confirm_write_actions": getattr(chat, "confirm_write_actions", True),
}
)
async def handle_chat_history(self, data: dict):
payload = ChatHistoryPayload(**data)
messages = self.director.chat_history(payload.chat_id)
chat = self.director.chat_get(payload.chat_id)
mode = chat.mode if chat else "normal"
confirm_write_actions = chat.confirm_write_actions if chat else True
self.websocket_handler.queue_put(
{
"type": "director",
"action": "chat_history",
"chat_id": payload.chat_id,
"messages": [m.model_dump() for m in messages],
"token_total": sum(util.count_tokens(str(m)) for m in messages),
"mode": mode,
"confirm_write_actions": confirm_write_actions,
}
)
async def handle_chat_send(self, data: dict):
payload = ChatSendPayload(**data)
_on_update, _on_done, _on_compacting, _on_compacted = (
self._make_generation_callbacks(payload.chat_id)
)
# delegate the generation to the agent mixin method in background
# Determine confirm_write_actions for this chat context
chat = self.director.chat_get(payload.chat_id)
cwa = chat.confirm_write_actions if chat else True
task = create_task_with_chat_context(
self.director.chat_send,
payload.chat_id,
payload.chat_id,
payload.message,
on_update=_on_update,
on_done=_on_done,
on_compacting=_on_compacting,
on_compacted=_on_compacted,
confirm_write_actions=cwa,
)
self._attach_task_done_callback(task, payload.chat_id)
async def handle_chat_clear(self, data: dict):
payload = ChatClearPayload(**data)
cleared = self.director.chat_clear(payload.chat_id)
self.websocket_handler.queue_put(
{
"type": "director",
"action": "chat_cleared",
"chat_id": payload.chat_id,
"cleared": cleared,
}
)
if cleared:
# Emit the reset greeting history so UI updates immediately
messages = self.director.chat_history(payload.chat_id)
chat = self.director.chat_get(payload.chat_id)
mode = chat.mode if chat else "normal"
confirm_write_actions = chat.confirm_write_actions if chat else True
self.websocket_handler.queue_put(
{
"type": "director",
"action": "chat_history",
"chat_id": payload.chat_id,
"messages": [m.model_dump() for m in messages],
"mode": mode,
"confirm_write_actions": confirm_write_actions,
}
)
async def handle_chat_remove_message(self, data: dict):
payload = ChatRemoveMessagePayload(**data)
chat = self.director.chat_remove_message(payload.chat_id, payload.message_id)
if not chat:
return
self.websocket_handler.queue_put(
{
"type": "director",
"action": "chat_history",
"chat_id": payload.chat_id,
"messages": [m.model_dump() for m in chat.messages],
"token_total": sum(util.count_tokens(str(m)) for m in chat.messages),
"mode": chat.mode,
"confirm_write_actions": getattr(chat, "confirm_write_actions", True),
}
)
async def handle_chat_regenerate(self, data: dict):
payload = ChatRegeneratePayload(**data)
_on_update, _on_done, _on_compacting, _on_compacted = (
self._make_generation_callbacks(payload.chat_id)
)
task = create_task_with_chat_context(
self.director.chat_regenerate_last,
payload.chat_id,
payload.chat_id,
on_update=_on_update,
on_done=_on_done,
on_compacting=_on_compacting,
on_compacted=_on_compacted,
)
self._attach_task_done_callback(task, payload.chat_id)
async def handle_confirm_action(self, data: dict):
payload = ConfirmActionPayload(**data)
log.debug("director.chat.websocket.handle_confirm_action", payload=payload)
scene: "Scene" = self.scene
key: str = f"_director_chat_action_confirm_{payload.id}"
if key not in scene.nodegraph_state.shared:
log.error(
"director.chat.websocket.handle_confirm_action.key_not_found", key=key
)
return
scene.nodegraph_state.shared[key] = payload.decision
self.websocket_handler.queue_put(
{
"type": "director",
"action": "confirm_action_processed",
"chat_id": payload.chat_id,
"id": payload.id,
"decision": payload.decision,
}
)
async def handle_chat_update_mode(self, data: dict):
payload = ChatUpdateModePayload(**data)
# Update the chat mode in the director
chat = self.director.chat_get(payload.chat_id)
if chat:
chat.mode = payload.mode
# Persist the updated chat state
self.director.chat_set_chat_state(chat.model_dump())
async def handle_chat_update_confirm_write_actions(self, data: dict):
payload = ChatUpdateConfirmWriteActionsPayload(**data)
chat = self.director.chat_get(payload.chat_id)
if chat:
chat.confirm_write_actions = payload.confirm_write_actions
self.director.chat_set_chat_state(chat.model_dump())

View File

@@ -305,6 +305,16 @@ class GuideSceneMixin:
"max_tokens": self.client.max_token_length,
},
)
await self.emit_message(
"Actor Guidance",
response,
meta={
"action": "actor guidance",
"character": character.name,
},
)
return strip_partial_sentences(response).strip()
@set_processing
@@ -328,4 +338,13 @@ class GuideSceneMixin:
"max_tokens": self.client.max_token_length,
},
)
await self.emit_message(
"Narrator Guidance",
response,
meta={
"action": "narrator guidance",
},
)
return strip_partial_sentences(response).strip()

View File

@@ -0,0 +1,154 @@
{
"title": "Agent Report Issue",
"id": "cfbec838-8e88-4dc0-89d3-f4a066f9b70f",
"properties": {},
"x": 0,
"y": 0,
"width": 200,
"height": 100,
"collapsed": false,
"inherited": false,
"registry": "agents/director/chat/agentReportIssue",
"nodes": {
"525b49ff-665b-40ae-8548-77b7be248745": {
"title": "task",
"id": "525b49ff-665b-40ae-8548-77b7be248745",
"properties": {
"name": "task",
"typ": "str",
"instructions": "Briefly describe the task that was not completed."
},
"x": 23,
"y": 78,
"width": 210,
"height": 106,
"collapsed": false,
"inherited": false,
"registry": "focal/Argument",
"base_type": "core/Node"
},
"274006b2-0cda-47d2-9e7a-5182affbc30d": {
"title": "report",
"id": "274006b2-0cda-47d2-9e7a-5182affbc30d",
"properties": {
"name": "issue",
"typ": "str",
"instructions": "Explanatioin of any issues you faced that prevented you from fulfilling the specified task."
},
"x": 33,
"y": 268,
"width": 210,
"height": 106,
"collapsed": false,
"inherited": false,
"registry": "focal/Argument",
"base_type": "core/Node"
},
"03aa565e-2cd9-401e-bb1b-750aecd159e3": {
"title": "Advanced Format",
"id": "03aa565e-2cd9-401e-bb1b-750aecd159e3",
"properties": {
"template": "Could not complete all tasks.\n\nTASK: {task}\n\nISSUE: {issue}"
},
"x": 313,
"y": 138,
"width": 210,
"height": 153,
"collapsed": false,
"inherited": false,
"registry": "data/string/AdvancedFormat",
"dynamic_inputs": [
{
"name": "item0",
"type": "*"
},
{
"name": "item1",
"type": "*"
}
],
"base_type": "core/DynamicSocketNodeBase"
},
"a0b1972c-5a0f-40aa-a30d-b299fab107c2": {
"title": "Return",
"id": "a0b1972c-5a0f-40aa-a30d-b299fab107c2",
"properties": {},
"x": 590,
"y": 180,
"width": 140,
"height": 26,
"collapsed": false,
"inherited": false,
"registry": "core/functions/Return",
"base_type": "core/Node"
},
"16db1b24-2713-46f2-a329-2b7aa1b77f0e": {
"title": "AI Function Callback Metadata",
"id": "16db1b24-2713-46f2-a329-2b7aa1b77f0e",
"properties": {
"instructions": "Report back if you are unable to complete a task and why so assistance can be given to you.",
"examples": [
{
"task": "I was tasked to update existing context 'Dragon scales'.",
"issue": "I could not locate the Context ID for the entry."
}
]
},
"x": 770,
"y": 180,
"width": 244,
"height": 82,
"collapsed": false,
"inherited": false,
"registry": "focal/Metadata",
"base_type": "core/Node"
}
},
"edges": {
"525b49ff-665b-40ae-8548-77b7be248745.value": [
"03aa565e-2cd9-401e-bb1b-750aecd159e3.item0"
],
"274006b2-0cda-47d2-9e7a-5182affbc30d.value": [
"03aa565e-2cd9-401e-bb1b-750aecd159e3.item1"
],
"03aa565e-2cd9-401e-bb1b-750aecd159e3.result": [
"a0b1972c-5a0f-40aa-a30d-b299fab107c2.value"
],
"a0b1972c-5a0f-40aa-a30d-b299fab107c2.value": [
"16db1b24-2713-46f2-a329-2b7aa1b77f0e.state"
]
},
"groups": [
{
"title": "Process",
"x": 4,
"y": 3,
"width": 1119,
"height": 381,
"color": "#3f789e",
"font_size": 24,
"inherited": false
}
],
"comments": [],
"extends": null,
"base_type": "core/functions/Function",
"inputs": [],
"outputs": [
{
"id": "1792ee7b-f576-4f80-8df9-7bcd94e95e00",
"name": "fn",
"optional": false,
"group": null,
"socket_type": "function"
}
],
"module_properties": {},
"style": {
"title_color": "#573a2e",
"node_color": "#392f2c",
"icon": "F0295",
"auto_title": null,
"counterpart": null
}
}

View File

@@ -0,0 +1,808 @@
{
"title": "Character Context",
"id": "8eab0bc0-009c-4868-a9dd-a3b4acadb919",
"properties": {},
"x": 0,
"y": 0,
"width": 200,
"height": 100,
"collapsed": false,
"inherited": false,
"registry": "agents/director/chat/characterContext",
"nodes": {
"9aa71776-f943-4182-ad7e-7f7ac7579d01": {
"title": "Switch",
"id": "9aa71776-f943-4182-ad7e-7f7ac7579d01",
"properties": {
"pass_through": true
},
"x": 278,
"y": 280,
"width": 210,
"height": 78,
"collapsed": false,
"inherited": false,
"registry": "core/Switch",
"base_type": "core/Node"
},
"715f1d40-c730-4f06-8690-22e5cdab0e7c": {
"title": "GET local.character",
"id": "715f1d40-c730-4f06-8690-22e5cdab0e7c",
"properties": {
"name": "character",
"scope": "local"
},
"x": 28,
"y": 250,
"width": 210,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "state/GetState",
"base_type": "core/Node"
},
"c55d0ec9-927b-4eff-a5d5-cfdf1ea28560": {
"title": "Attributes Header",
"id": "c55d0ec9-927b-4eff-a5d5-cfdf1ea28560",
"properties": {
"template": "{character.name}'s Attributes"
},
"x": 1197,
"y": 9,
"width": 210,
"height": 133,
"collapsed": true,
"inherited": false,
"registry": "data/string/AdvancedFormat",
"dynamic_inputs": [
{
"name": "item0",
"type": "*"
}
],
"base_type": "core/DynamicSocketNodeBase"
},
"b998c1c4-7e12-4882-b8d9-c0cc910963b9": {
"title": "Dynamic Instruction",
"id": "b998c1c4-7e12-4882-b8d9-c0cc910963b9",
"properties": {
"header": null,
"content": null
},
"x": 1463,
"y": 283,
"width": 228,
"height": 102,
"collapsed": false,
"inherited": false,
"registry": "agents/DynamicInstruction",
"base_type": "core/Node"
},
"ab632855-c15e-4911-8729-ba3b625935c5": {
"title": "Dynamic Instruction",
"id": "ab632855-c15e-4911-8729-ba3b625935c5",
"properties": {
"header": null,
"content": null
},
"x": 1473,
"y": 503,
"width": 228,
"height": 102,
"collapsed": false,
"inherited": false,
"registry": "agents/DynamicInstruction",
"base_type": "core/Node"
},
"9416a022-802b-4be6-a36b-81fcb732f7cd": {
"title": "Dynamic Instruction",
"id": "9416a022-802b-4be6-a36b-81fcb732f7cd",
"properties": {
"header": null,
"content": null
},
"x": 1473,
"y": 34,
"width": 228,
"height": 102,
"collapsed": false,
"inherited": false,
"registry": "agents/DynamicInstruction",
"base_type": "core/Node"
},
"8d97d5b1-0855-430e-8b34-811d238c727a": {
"title": "SET local.character_context",
"id": "8d97d5b1-0855-430e-8b34-811d238c727a",
"properties": {
"name": "character_context",
"scope": "local"
},
"x": 1976,
"y": 240,
"width": 227,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "state/SetState",
"base_type": "core/Node"
},
"2c781216-86dd-4a83-ad71-256d1889bcdf": {
"title": "GET local.character",
"id": "2c781216-86dd-4a83-ad71-256d1889bcdf",
"properties": {
"name": "character",
"scope": "local"
},
"x": 37,
"y": 1026,
"width": 210,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "state/GetState",
"base_type": "core/Node"
},
"fa7c8a06-a631-4adf-a993-76d35001358d": {
"title": "GET local.character_context",
"id": "fa7c8a06-a631-4adf-a993-76d35001358d",
"properties": {
"name": "character_context",
"scope": "local"
},
"x": 27,
"y": 1216,
"width": 227,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "state/GetState",
"base_type": "core/Node"
},
"86469aa3-403e-453c-b4a5-f6998a13a601": {
"title": "OUT dynamic_instruction",
"id": "86469aa3-403e-453c-b4a5-f6998a13a601",
"properties": {
"output_type": "list",
"output_name": "character_context",
"num": 1
},
"x": 387,
"y": 1236,
"width": 210,
"height": 106,
"collapsed": false,
"inherited": false,
"registry": "core/Output",
"base_type": "core/Node"
},
"4c159f82-1858-45e3-922b-36b485bfa7f9": {
"title": "Stage 1",
"id": "4c159f82-1858-45e3-922b-36b485bfa7f9",
"properties": {
"stage": 1
},
"x": 2242,
"y": 237,
"width": 210,
"height": 118,
"collapsed": false,
"inherited": false,
"registry": "core/Stage",
"base_type": "core/Node"
},
"bd428cde-493e-4b50-ad9f-3d2800c9f911": {
"title": "Dertails Header",
"id": "bd428cde-493e-4b50-ad9f-3d2800c9f911",
"properties": {
"template": "{character.name}'s Detailed Information"
},
"x": 1212,
"y": 227,
"width": 210,
"height": 133,
"collapsed": true,
"inherited": false,
"registry": "data/string/AdvancedFormat",
"dynamic_inputs": [
{
"name": "item0",
"type": "*"
}
],
"base_type": "core/DynamicSocketNodeBase"
},
"f399112f-2cd4-4354-b786-4b3d81e046fc": {
"title": "Dertails Header",
"id": "f399112f-2cd4-4354-b786-4b3d81e046fc",
"properties": {
"template": "{character.name}'s Description"
},
"x": 1212,
"y": 457,
"width": 210,
"height": 133,
"collapsed": true,
"inherited": false,
"registry": "data/string/AdvancedFormat",
"dynamic_inputs": [
{
"name": "item0",
"type": "*"
}
],
"base_type": "core/DynamicSocketNodeBase"
},
"091f49f1-fb01-4ee9-a44f-3d60184580a6": {
"title": "List Collector",
"id": "091f49f1-fb01-4ee9-a44f-3d60184580a6",
"properties": {},
"x": 1495,
"y": 793,
"width": 140,
"height": 101,
"collapsed": false,
"inherited": false,
"registry": "data/ListCollector",
"dynamic_inputs": [
{
"name": "item0",
"type": "*"
},
{
"name": "item1",
"type": "*"
}
],
"base_type": "core/DynamicSocketNodeBase"
},
"34b7def1-91b9-405a-ad02-a359a4216fc6": {
"title": "Dynamic Instruction",
"id": "34b7def1-91b9-405a-ad02-a359a4216fc6",
"properties": {
"header": "Character Configuration",
"content": null
},
"x": 1675,
"y": 753,
"width": 228,
"height": 102,
"collapsed": false,
"inherited": false,
"registry": "agents/DynamicInstruction",
"base_type": "core/Node"
},
"71494b49-7c71-4de4-a18e-337005c8f7d4": {
"title": "RSwitch Advanced",
"id": "71494b49-7c71-4de4-a18e-337005c8f7d4",
"properties": {},
"x": 955,
"y": 333,
"width": 176,
"height": 66,
"collapsed": true,
"inherited": false,
"registry": "core/RSwitchAdvanced",
"base_type": "core/Node"
},
"3f8ca797-dbc1-4aa9-8f4e-84302380bbc9": {
"title": "GET local.include_details",
"id": "3f8ca797-dbc1-4aa9-8f4e-84302380bbc9",
"properties": {
"name": "include_details",
"scope": "local"
},
"x": 935,
"y": 303,
"width": 210,
"height": 122,
"collapsed": true,
"inherited": false,
"registry": "state/GetState",
"base_type": "core/Node"
},
"37c84835-3318-4ca1-acf2-f405de7d7e3e": {
"title": "GET local.include_details",
"id": "37c84835-3318-4ca1-acf2-f405de7d7e3e",
"properties": {
"name": "include_details",
"scope": "local"
},
"x": 475,
"y": 663,
"width": 210,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "state/GetState",
"base_type": "core/Node"
},
"0110003a-ec78-4e90-aad5-5caa4219c29e": {
"title": "SET local.include_details",
"id": "0110003a-ec78-4e90-aad5-5caa4219c29e",
"properties": {
"name": "include_details",
"scope": "local"
},
"x": 350,
"y": -836,
"width": 210,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "state/SetState",
"base_type": "core/Node"
},
"899dcae1-d8e3-4895-9c94-ff714cb9f100": {
"title": "SET local.include_details",
"id": "899dcae1-d8e3-4895-9c94-ff714cb9f100",
"properties": {
"name": "include_details",
"scope": "local"
},
"x": 348,
"y": -573,
"width": 210,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "state/SetState",
"base_type": "core/Node"
},
"c71781be-b177-45af-9c8f-c1ebf157f268": {
"title": "Input Socket",
"id": "c71781be-b177-45af-9c8f-c1ebf157f268",
"properties": {
"input_type": "character",
"input_name": "character",
"input_optional": false,
"input_group": "",
"num": 0
},
"x": 30,
"y": -253,
"width": 210,
"height": 154,
"collapsed": false,
"inherited": false,
"registry": "core/Input",
"base_type": "core/Node"
},
"6d4f53fc-e2fa-406f-816b-d078538502ef": {
"title": "SET local.character",
"id": "6d4f53fc-e2fa-406f-816b-d078538502ef",
"properties": {
"name": "character",
"scope": "local"
},
"x": 330,
"y": -233,
"width": 210,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "state/SetState",
"base_type": "core/Node"
},
"c0fa5a08-066b-4adc-b980-9daa5f80763e": {
"title": "Stage 0",
"id": "c0fa5a08-066b-4adc-b980-9daa5f80763e",
"properties": {
"stage": 0
},
"x": 790,
"y": -563,
"width": 210,
"height": 118,
"collapsed": false,
"inherited": false,
"registry": "core/Stage",
"base_type": "core/Node"
},
"481ee93d-769d-4283-8e72-25cc3237a105": {
"title": "Module Style",
"id": "481ee93d-769d-4283-8e72-25cc3237a105",
"properties": {
"node_color": "#27233a",
"title_color": "#3d315b",
"auto_title": null,
"icon": "F09DE"
},
"x": 820,
"y": -913,
"width": 210,
"height": 110,
"collapsed": false,
"inherited": false,
"registry": "util/ModuleStyle",
"base_type": "core/Node"
},
"931d34b1-126a-48a8-80f9-0af0ffc6c2a8": {
"title": "PROP include_details",
"id": "931d34b1-126a-48a8-80f9-0af0ffc6c2a8",
"properties": {
"property_name": "include_config",
"property_type": "bool",
"default": "false",
"choices": [],
"description": "Include background details",
"num": 1
},
"x": 28,
"y": -603,
"width": 256,
"height": 198,
"collapsed": false,
"inherited": false,
"registry": "core/ModuleProperty",
"base_type": "core/Node"
},
"dd8dc917-4a74-49db-a9c3-93ea33c2f55a": {
"title": "PROP include_details",
"id": "dd8dc917-4a74-49db-a9c3-93ea33c2f55a",
"properties": {
"property_name": "include_details",
"property_type": "bool",
"default": "true",
"choices": [],
"description": "Include background details",
"num": 0
},
"x": 30,
"y": -865,
"width": 256,
"height": 198,
"collapsed": false,
"inherited": false,
"registry": "core/ModuleProperty",
"base_type": "core/Node"
},
"cfb75f37-92d1-4111-921e-ee783762cf72": {
"title": "OUT character",
"id": "cfb75f37-92d1-4111-921e-ee783762cf72",
"properties": {
"output_type": "character",
"output_name": "character",
"num": 0
},
"x": 380,
"y": 1020,
"width": 210,
"height": 106,
"collapsed": false,
"inherited": false,
"registry": "core/Output",
"base_type": "core/Node"
},
"846f1c33-4aad-470c-8c40-a84b925d742c": {
"title": "RSwitch Advanced",
"id": "846f1c33-4aad-470c-8c40-a84b925d742c",
"properties": {},
"x": 870,
"y": 840,
"width": 176,
"height": 66,
"collapsed": false,
"inherited": false,
"registry": "core/RSwitchAdvanced",
"base_type": "core/Node"
},
"8da4f2ff-1f1e-4b6e-8fa2-7be93d28c91d": {
"title": "Render Context IDs",
"id": "8da4f2ff-1f1e-4b6e-8fa2-7be93d28c91d",
"properties": {
"display_mode": "compact"
},
"x": 1175,
"y": 843,
"width": 210,
"height": 78,
"collapsed": false,
"inherited": false,
"registry": "context_id/RenderContextIDs",
"base_type": "core/Node"
},
"9a05071c-d55c-48ea-a5de-b2f5b21a32dc": {
"title": "Render Context IDs",
"id": "9a05071c-d55c-48ea-a5de-b2f5b21a32dc",
"properties": {
"display_mode": "compact"
},
"x": 1170,
"y": 530,
"width": 210,
"height": 78,
"collapsed": false,
"inherited": false,
"registry": "context_id/RenderContextIDs",
"base_type": "core/Node"
},
"891ddc97-7225-4ba2-911b-fb5882a003a9": {
"title": "RSwitch Advanced",
"id": "891ddc97-7225-4ba2-911b-fb5882a003a9",
"properties": {},
"x": 870,
"y": 680,
"width": 176,
"height": 66,
"collapsed": false,
"inherited": false,
"registry": "core/RSwitchAdvanced",
"base_type": "core/Node"
},
"ab91528b-409d-46f5-9881-f6c0e2b12297": {
"title": "Render Context IDs",
"id": "ab91528b-409d-46f5-9881-f6c0e2b12297",
"properties": {
"display_mode": "compact"
},
"x": 1180,
"y": 680,
"width": 210,
"height": 78,
"collapsed": false,
"inherited": false,
"registry": "context_id/RenderContextIDs",
"base_type": "core/Node"
},
"36a69808-2a2f-47ab-871c-79cde27bda19": {
"title": "Render Context IDs",
"id": "36a69808-2a2f-47ab-871c-79cde27bda19",
"properties": {
"display_mode": "subsection"
},
"x": 1170,
"y": 300,
"width": 210,
"height": 78,
"collapsed": false,
"inherited": false,
"registry": "context_id/RenderContextIDs",
"base_type": "core/Node"
},
"6072e646-09b3-435d-ba1b-51227aa0865b": {
"title": "Render Context IDs",
"id": "6072e646-09b3-435d-ba1b-51227aa0865b",
"properties": {
"display_mode": "normal"
},
"x": 1160,
"y": 80,
"width": 210,
"height": 78,
"collapsed": false,
"inherited": false,
"registry": "context_id/RenderContextIDs",
"base_type": "core/Node"
},
"caf10f6f-b3c3-492b-aa45-6f3200f28914": {
"title": "List Collector",
"id": "caf10f6f-b3c3-492b-aa45-6f3200f28914",
"properties": {},
"x": 1796,
"y": 272,
"width": 140,
"height": 141,
"collapsed": false,
"inherited": false,
"registry": "data/ListCollector",
"dynamic_inputs": [
{
"name": "item0",
"type": "*"
},
{
"name": "item1",
"type": "*"
},
{
"name": "item2",
"type": "*"
},
{
"name": "item3",
"type": "*"
}
],
"base_type": "core/DynamicSocketNodeBase"
},
"ab90ab05-cbb0-45af-8d58-57e71d5e528f": {
"title": "Character Context IDs",
"id": "ab90ab05-cbb0-45af-8d58-57e71d5e528f",
"properties": {},
"x": 512,
"y": 267,
"width": 262,
"height": 126,
"collapsed": false,
"inherited": false,
"registry": "context_id/CharacterContextIDs",
"base_type": "core/Node"
}
},
"edges": {
"9aa71776-f943-4182-ad7e-7f7ac7579d01.yes": [
"ab90ab05-cbb0-45af-8d58-57e71d5e528f.character"
],
"715f1d40-c730-4f06-8690-22e5cdab0e7c.value": [
"9aa71776-f943-4182-ad7e-7f7ac7579d01.value"
],
"c55d0ec9-927b-4eff-a5d5-cfdf1ea28560.result": [
"9416a022-802b-4be6-a36b-81fcb732f7cd.header"
],
"b998c1c4-7e12-4882-b8d9-c0cc910963b9.dynamic_instruction": [
"caf10f6f-b3c3-492b-aa45-6f3200f28914.item1"
],
"ab632855-c15e-4911-8729-ba3b625935c5.dynamic_instruction": [
"caf10f6f-b3c3-492b-aa45-6f3200f28914.item2"
],
"9416a022-802b-4be6-a36b-81fcb732f7cd.dynamic_instruction": [
"caf10f6f-b3c3-492b-aa45-6f3200f28914.item0"
],
"8d97d5b1-0855-430e-8b34-811d238c727a.value": [
"4c159f82-1858-45e3-922b-36b485bfa7f9.state"
],
"2c781216-86dd-4a83-ad71-256d1889bcdf.value": [
"cfb75f37-92d1-4111-921e-ee783762cf72.value"
],
"fa7c8a06-a631-4adf-a993-76d35001358d.value": [
"86469aa3-403e-453c-b4a5-f6998a13a601.value"
],
"bd428cde-493e-4b50-ad9f-3d2800c9f911.result": [
"b998c1c4-7e12-4882-b8d9-c0cc910963b9.header"
],
"f399112f-2cd4-4354-b786-4b3d81e046fc.result": [
"ab632855-c15e-4911-8729-ba3b625935c5.header"
],
"091f49f1-fb01-4ee9-a44f-3d60184580a6.list": [
"34b7def1-91b9-405a-ad02-a359a4216fc6.content"
],
"34b7def1-91b9-405a-ad02-a359a4216fc6.dynamic_instruction": [
"caf10f6f-b3c3-492b-aa45-6f3200f28914.item3"
],
"71494b49-7c71-4de4-a18e-337005c8f7d4.yes": [
"36a69808-2a2f-47ab-871c-79cde27bda19.items"
],
"3f8ca797-dbc1-4aa9-8f4e-84302380bbc9.value": [
"71494b49-7c71-4de4-a18e-337005c8f7d4.check"
],
"37c84835-3318-4ca1-acf2-f405de7d7e3e.value": [
"846f1c33-4aad-470c-8c40-a84b925d742c.check",
"891ddc97-7225-4ba2-911b-fb5882a003a9.check"
],
"0110003a-ec78-4e90-aad5-5caa4219c29e.value": [
"c0fa5a08-066b-4adc-b980-9daa5f80763e.state"
],
"899dcae1-d8e3-4895-9c94-ff714cb9f100.value": [
"c0fa5a08-066b-4adc-b980-9daa5f80763e.state_b"
],
"c71781be-b177-45af-9c8f-c1ebf157f268.value": [
"6d4f53fc-e2fa-406f-816b-d078538502ef.value"
],
"6d4f53fc-e2fa-406f-816b-d078538502ef.value": [
"c0fa5a08-066b-4adc-b980-9daa5f80763e.state_c"
],
"931d34b1-126a-48a8-80f9-0af0ffc6c2a8.value": [
"899dcae1-d8e3-4895-9c94-ff714cb9f100.value"
],
"dd8dc917-4a74-49db-a9c3-93ea33c2f55a.name": [
"0110003a-ec78-4e90-aad5-5caa4219c29e.name"
],
"dd8dc917-4a74-49db-a9c3-93ea33c2f55a.value": [
"0110003a-ec78-4e90-aad5-5caa4219c29e.value"
],
"846f1c33-4aad-470c-8c40-a84b925d742c.yes": [
"8da4f2ff-1f1e-4b6e-8fa2-7be93d28c91d.items"
],
"8da4f2ff-1f1e-4b6e-8fa2-7be93d28c91d.rendered": [
"091f49f1-fb01-4ee9-a44f-3d60184580a6.item1"
],
"9a05071c-d55c-48ea-a5de-b2f5b21a32dc.rendered": [
"ab632855-c15e-4911-8729-ba3b625935c5.content"
],
"891ddc97-7225-4ba2-911b-fb5882a003a9.yes": [
"ab91528b-409d-46f5-9881-f6c0e2b12297.items"
],
"ab91528b-409d-46f5-9881-f6c0e2b12297.rendered": [
"091f49f1-fb01-4ee9-a44f-3d60184580a6.item0"
],
"36a69808-2a2f-47ab-871c-79cde27bda19.rendered": [
"b998c1c4-7e12-4882-b8d9-c0cc910963b9.content"
],
"6072e646-09b3-435d-ba1b-51227aa0865b.rendered": [
"9416a022-802b-4be6-a36b-81fcb732f7cd.content"
],
"caf10f6f-b3c3-492b-aa45-6f3200f28914.list": [
"8d97d5b1-0855-430e-8b34-811d238c727a.value"
],
"ab90ab05-cbb0-45af-8d58-57e71d5e528f.character": [
"c55d0ec9-927b-4eff-a5d5-cfdf1ea28560.item0",
"bd428cde-493e-4b50-ad9f-3d2800c9f911.item0",
"f399112f-2cd4-4354-b786-4b3d81e046fc.item0"
],
"ab90ab05-cbb0-45af-8d58-57e71d5e528f.attributes": [
"6072e646-09b3-435d-ba1b-51227aa0865b.items"
],
"ab90ab05-cbb0-45af-8d58-57e71d5e528f.details": [
"71494b49-7c71-4de4-a18e-337005c8f7d4.yes"
],
"ab90ab05-cbb0-45af-8d58-57e71d5e528f.description": [
"9a05071c-d55c-48ea-a5de-b2f5b21a32dc.items"
],
"ab90ab05-cbb0-45af-8d58-57e71d5e528f.acting_instructions": [
"891ddc97-7225-4ba2-911b-fb5882a003a9.yes"
],
"ab90ab05-cbb0-45af-8d58-57e71d5e528f.example_dialogue": [
"846f1c33-4aad-470c-8c40-a84b925d742c.yes"
]
},
"groups": [
{
"title": "Process",
"x": 3,
"y": -71,
"width": 2474,
"height": 1017,
"color": "#3f789e",
"font_size": 24,
"inherited": false
},
{
"title": "Validation",
"x": 3,
"y": -993,
"width": 1052,
"height": 919,
"color": "#b58b2a",
"font_size": 24,
"inherited": false
},
{
"title": "Output",
"x": 3,
"y": 949,
"width": 630,
"height": 421,
"color": "#8A8",
"font_size": 24,
"inherited": false
}
],
"comments": [],
"extends": null,
"base_type": "core/Graph",
"inputs": [],
"outputs": [],
"module_properties": {
"include_details": {
"name": "include_details",
"description": "Include background details",
"type": "bool",
"default": true,
"choices": [],
"readonly": false,
"step": null,
"min": null,
"max": null,
"ephemeral": false
},
"include_config": {
"name": "include_config",
"description": "Include background details",
"type": "bool",
"default": false,
"choices": [],
"readonly": false,
"step": null,
"min": null,
"max": null,
"ephemeral": false
}
},
"style": {
"title_color": "#3d315b",
"node_color": "#27233a",
"icon": "F09DE",
"auto_title": null,
"counterpart": null
}
}

View File

@@ -0,0 +1,412 @@
{
"title": "Character Names Context",
"id": "18245c31-f3f4-4c03-babe-2254586d52d4",
"properties": {},
"x": 0,
"y": 0,
"width": 200,
"height": 100,
"collapsed": false,
"inherited": false,
"registry": "agents/director/chat/characterNamesContext",
"nodes": {
"2cfbcc4a-023e-4b6f-b4dc-5ed01d6c8f2b": {
"title": "OUT state",
"id": "2cfbcc4a-023e-4b6f-b4dc-5ed01d6c8f2b",
"properties": {
"output_type": "any",
"output_name": "state",
"num": 0
},
"x": 420,
"y": 80,
"width": 210,
"height": 106,
"collapsed": false,
"inherited": false,
"registry": "core/Output",
"base_type": "core/Node"
},
"78f93251-8f9d-4d5c-99cd-54534e40a827": {
"title": "Input Socket",
"id": "78f93251-8f9d-4d5c-99cd-54534e40a827",
"properties": {
"input_type": "any",
"input_name": "state",
"input_optional": false,
"input_group": "",
"num": 0
},
"x": 40,
"y": 70,
"width": 210,
"height": 154,
"collapsed": false,
"inherited": false,
"registry": "core/Input",
"base_type": "core/Node"
},
"bd2c35fa-b219-4dcb-8b64-cfb35e898149": {
"title": "item",
"id": "bd2c35fa-b219-4dcb-8b64-cfb35e898149",
"properties": {
"name": "item",
"typ": "any"
},
"x": -1456,
"y": 70,
"width": 210,
"height": 82,
"collapsed": false,
"inherited": false,
"registry": "core/functions/Argument",
"base_type": "core/Node"
},
"6bce6796-df9d-4b41-8096-800406b1c8b4": {
"title": "Unpack Character",
"id": "6bce6796-df9d-4b41-8096-800406b1c8b4",
"properties": {},
"x": -1196,
"y": 70,
"width": 212,
"height": 146,
"collapsed": false,
"inherited": false,
"registry": "scene/UnpackCharacter",
"base_type": "core/Node"
},
"09ae2df0-0247-4bae-9764-e6046803832b": {
"title": "Excerpt",
"id": "09ae2df0-0247-4bae-9764-e6046803832b",
"properties": {
"length": 100,
"add_ellipsis": true
},
"x": -936,
"y": 170,
"width": 210,
"height": 82,
"collapsed": false,
"inherited": false,
"registry": "data/string/Excerpt",
"base_type": "core/Node"
},
"0727e4cd-8f05-4e6c-9cce-e9361e86857d": {
"title": "Advanced Format",
"id": "0727e4cd-8f05-4e6c-9cce-e9361e86857d",
"properties": {
"template": "- `{name}`: {result}\n"
},
"x": -656,
"y": 70,
"width": 210,
"height": 153,
"collapsed": false,
"inherited": false,
"registry": "data/string/AdvancedFormat",
"dynamic_inputs": [
{
"name": "item0",
"type": "*"
},
{
"name": "item1",
"type": "*"
}
],
"base_type": "core/DynamicSocketNodeBase"
},
"697fa805-18bf-4634-8b18-38f46a71f3fb": {
"title": "Return",
"id": "697fa805-18bf-4634-8b18-38f46a71f3fb",
"properties": {},
"x": -386,
"y": 140,
"width": 140,
"height": 26,
"collapsed": false,
"inherited": false,
"registry": "core/functions/Return",
"base_type": "core/Node"
},
"46df5bea-50b7-40b3-a9db-917bf11478b0": {
"title": "DEF list_character",
"id": "46df5bea-50b7-40b3-a9db-917bf11478b0",
"properties": {
"name": "list_character"
},
"x": -226,
"y": 120,
"width": 210,
"height": 78,
"collapsed": false,
"inherited": false,
"registry": "core/functions/DefineFunction",
"base_type": "core/Node"
},
"bb8bf088-9dea-4e7d-a7c7-8abdd29992f2": {
"title": "FN list_character",
"id": "bb8bf088-9dea-4e7d-a7c7-8abdd29992f2",
"properties": {
"name": "list_character"
},
"x": 812,
"y": 508,
"width": 210,
"height": 78,
"collapsed": true,
"inherited": false,
"registry": "core/functions/GetFunction",
"base_type": "core/Node"
},
"6d7aabc0-740e-4820-93d0-9fad9de50fca": {
"title": "true",
"id": "6d7aabc0-740e-4820-93d0-9fad9de50fca",
"properties": {
"value": true
},
"x": 652,
"y": 528,
"width": 210,
"height": 58,
"collapsed": true,
"inherited": false,
"registry": "core/MakeBool",
"base_type": "core/Node"
},
"d666367c-1b0a-4885-893b-e0211a417ca1": {
"title": "Call For Each",
"id": "d666367c-1b0a-4885-893b-e0211a417ca1",
"properties": {
"copy_items": false,
"argument_name": "item"
},
"x": 782,
"y": 538,
"width": 210,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "core/functions/CallForEach",
"base_type": "core/Node"
},
"b94ffd51-0fb8-4659-8ed1-9e94d6d8565c": {
"title": "Make Text",
"id": "b94ffd51-0fb8-4659-8ed1-9e94d6d8565c",
"properties": {
"value": "Persistent Character Listing"
},
"x": 350,
"y": 410,
"width": 210,
"height": 58,
"collapsed": false,
"inherited": false,
"registry": "data/string/MakeText",
"base_type": "core/Node"
},
"a39370c3-7cf6-42c9-84a5-559dedcec096": {
"title": "RSwitch",
"id": "a39370c3-7cf6-42c9-84a5-559dedcec096",
"properties": {},
"x": 680,
"y": 330,
"width": 140,
"height": 66,
"collapsed": false,
"inherited": false,
"registry": "core/RSwitch",
"base_type": "core/Node"
},
"1bcc2cb0-e297-4911-9659-44c65a6b508c": {
"title": "Dynamic Instruction",
"id": "1bcc2cb0-e297-4911-9659-44c65a6b508c",
"properties": {
"header": "Characters",
"content": null
},
"x": 1090,
"y": 430,
"width": 228,
"height": 102,
"collapsed": false,
"inherited": false,
"registry": "agents/DynamicInstruction",
"base_type": "core/Node"
},
"fe9c236b-caca-4de4-acd0-06f6f81bfec7": {
"title": "OUT state",
"id": "fe9c236b-caca-4de4-acd0-06f6f81bfec7",
"properties": {
"output_type": "dynamic_instruction",
"output_name": "dynamic_instruction",
"num": 1
},
"x": 1390,
"y": 420,
"width": 270,
"height": 106,
"collapsed": false,
"inherited": false,
"registry": "core/Output",
"base_type": "core/Node"
},
"33e3ca03-5193-476e-a30c-cf2103b7406b": {
"title": "Module Style",
"id": "33e3ca03-5193-476e-a30c-cf2103b7406b",
"properties": {
"node_color": "#27233a",
"title_color": "#3d315b",
"auto_title": null,
"icon": "F09DE"
},
"x": 1430,
"y": 100,
"width": 210,
"height": 110,
"collapsed": false,
"inherited": false,
"registry": "util/ModuleStyle",
"base_type": "core/Node"
},
"9824a723-ee64-4e0d-ab50-0d4824e5799c": {
"title": "Input Socket",
"id": "9824a723-ee64-4e0d-ab50-0d4824e5799c",
"properties": {
"input_type": "str",
"input_name": "header",
"input_optional": true,
"input_group": "",
"num": 0
},
"x": 50,
"y": 280,
"width": 210,
"height": 154,
"collapsed": false,
"inherited": false,
"registry": "core/Input",
"base_type": "core/Node"
},
"38b09291-5ab2-4137-981d-4a8da7d8884a": {
"title": "List Characters",
"id": "38b09291-5ab2-4137-981d-4a8da7d8884a",
"properties": {
"character_status": "all"
},
"x": 332,
"y": 538,
"width": 228,
"height": 58,
"collapsed": false,
"inherited": false,
"registry": "scene/ListCharacters",
"base_type": "core/Node"
},
"b70aff1c-b46f-4538-88ac-281bbf0a31d7": {
"title": "Input Socket",
"id": "b70aff1c-b46f-4538-88ac-281bbf0a31d7",
"properties": {
"input_type": "any",
"input_name": "character_status",
"input_optional": true,
"input_group": "",
"num": 2
},
"x": 42,
"y": 488,
"width": 247,
"height": 154,
"collapsed": false,
"inherited": false,
"registry": "core/Input",
"base_type": "core/Node"
}
},
"edges": {
"78f93251-8f9d-4d5c-99cd-54534e40a827.value": [
"2cfbcc4a-023e-4b6f-b4dc-5ed01d6c8f2b.value"
],
"bd2c35fa-b219-4dcb-8b64-cfb35e898149.value": [
"6bce6796-df9d-4b41-8096-800406b1c8b4.character"
],
"6bce6796-df9d-4b41-8096-800406b1c8b4.name": [
"0727e4cd-8f05-4e6c-9cce-e9361e86857d.item0"
],
"6bce6796-df9d-4b41-8096-800406b1c8b4.description": [
"09ae2df0-0247-4bae-9764-e6046803832b.string"
],
"09ae2df0-0247-4bae-9764-e6046803832b.result": [
"0727e4cd-8f05-4e6c-9cce-e9361e86857d.item1"
],
"0727e4cd-8f05-4e6c-9cce-e9361e86857d.result": [
"697fa805-18bf-4634-8b18-38f46a71f3fb.value"
],
"697fa805-18bf-4634-8b18-38f46a71f3fb.value": [
"46df5bea-50b7-40b3-a9db-917bf11478b0.nodes"
],
"bb8bf088-9dea-4e7d-a7c7-8abdd29992f2.fn": [
"d666367c-1b0a-4885-893b-e0211a417ca1.fn"
],
"6d7aabc0-740e-4820-93d0-9fad9de50fca.value": [
"d666367c-1b0a-4885-893b-e0211a417ca1.state"
],
"d666367c-1b0a-4885-893b-e0211a417ca1.results": [
"1bcc2cb0-e297-4911-9659-44c65a6b508c.content"
],
"b94ffd51-0fb8-4659-8ed1-9e94d6d8565c.value": [
"a39370c3-7cf6-42c9-84a5-559dedcec096.no"
],
"a39370c3-7cf6-42c9-84a5-559dedcec096.value": [
"1bcc2cb0-e297-4911-9659-44c65a6b508c.header"
],
"1bcc2cb0-e297-4911-9659-44c65a6b508c.dynamic_instruction": [
"fe9c236b-caca-4de4-acd0-06f6f81bfec7.value"
],
"9824a723-ee64-4e0d-ab50-0d4824e5799c.value": [
"a39370c3-7cf6-42c9-84a5-559dedcec096.check",
"a39370c3-7cf6-42c9-84a5-559dedcec096.yes"
],
"38b09291-5ab2-4137-981d-4a8da7d8884a.characters": [
"d666367c-1b0a-4885-893b-e0211a417ca1.items"
],
"b70aff1c-b46f-4538-88ac-281bbf0a31d7.value": [
"38b09291-5ab2-4137-981d-4a8da7d8884a.character_status"
]
},
"groups": [
{
"title": "Group",
"x": -1481,
"y": -5,
"width": 1490,
"height": 282,
"color": "#b06634",
"font_size": 24,
"inherited": false
},
{
"title": "Group",
"x": 15,
"y": -5,
"width": 1719,
"height": 716,
"color": "#3f789e",
"font_size": 24,
"inherited": false
}
],
"comments": [],
"extends": null,
"base_type": "core/Graph",
"inputs": [],
"outputs": [],
"module_properties": {},
"style": {
"title_color": "#3d315b",
"node_color": "#27233a",
"icon": "F09DE",
"auto_title": null,
"counterpart": null
}
}

View File

@@ -0,0 +1,318 @@
{
"title": "Direct Context Update",
"id": "d5c3aa90-e999-45c9-a39d-5024775434ab",
"properties": {},
"x": 0,
"y": 0,
"width": 200,
"height": 100,
"collapsed": false,
"inherited": false,
"registry": "agents/director/chat/directContextUpdate",
"nodes": {
"c62f076c-8e48-4a1a-ac50-e31ea4766895": {
"title": "context_id",
"id": "c62f076c-8e48-4a1a-ac50-e31ea4766895",
"properties": {
"name": "context_id",
"typ": "str",
"instructions": "The exact Context ID given to you in your instructions."
},
"x": 26,
"y": 73,
"width": 210,
"height": 106,
"collapsed": false,
"inherited": false,
"registry": "focal/Argument",
"base_type": "core/Node"
},
"38961db6-7b4a-4ad1-a91a-1e8b151ee795": {
"title": "Validate Context ID Item",
"id": "38961db6-7b4a-4ad1-a91a-1e8b151ee795",
"properties": {
"error_message": ""
},
"x": 296,
"y": 83,
"width": 245,
"height": 158,
"collapsed": false,
"inherited": false,
"registry": "validation/ValidateContextIDItem",
"base_type": "core/Node"
},
"22020aa2-1867-40e5-9a7b-96e93f2945ed": {
"title": "value",
"id": "22020aa2-1867-40e5-9a7b-96e93f2945ed",
"properties": {
"name": "value",
"typ": "str",
"instructions": "The exact value given do you in your instructions."
},
"x": 26,
"y": 253,
"width": 210,
"height": 106,
"collapsed": false,
"inherited": false,
"registry": "focal/Argument",
"base_type": "core/Node"
},
"2bec2758-fe44-468a-a9ec-73d236f3a09f": {
"title": "Return",
"id": "2bec2758-fe44-468a-a9ec-73d236f3a09f",
"properties": {},
"x": 2246,
"y": 203,
"width": 140,
"height": 26,
"collapsed": false,
"inherited": false,
"registry": "core/functions/Return",
"base_type": "core/Node"
},
"6d188919-9f0e-4945-b9ff-d75ee92b0ce9": {
"title": "Path to Context ID",
"id": "6d188919-9f0e-4945-b9ff-d75ee92b0ce9",
"properties": {
"path": ""
},
"x": 606,
"y": 83,
"width": 210,
"height": 218,
"collapsed": false,
"inherited": false,
"registry": "context_id/PathToContextID",
"base_type": "core/Node"
},
"c8044776-d8a7-41b2-b800-374f0739a818": {
"title": "Diff",
"id": "c8044776-d8a7-41b2-b800-374f0739a818",
"properties": {},
"x": 814,
"y": 393,
"width": 140,
"height": 86,
"collapsed": false,
"inherited": false,
"registry": "util/Diff",
"base_type": "core/Node"
},
"db7c5f98-b007-4187-a47d-26490c3219bc": {
"title": "Context ID Set Value",
"id": "db7c5f98-b007-4187-a47d-26490c3219bc",
"properties": {
"path": ""
},
"x": 1584,
"y": 103,
"width": 262,
"height": 118,
"collapsed": false,
"inherited": false,
"registry": "context_id/ContextIDSetValue",
"base_type": "core/Node"
},
"8b71aa2a-3930-4c9a-ae81-590e65e66f56": {
"title": "Advanced Format",
"id": "8b71aa2a-3930-4c9a-ae81-590e65e66f56",
"properties": {
"template": "Changed `{context_id_item.context_id}`\nTarget: {human_id}\n\n``` diff\n{diff_plain}\n```"
},
"x": 1985,
"y": 227,
"width": 210,
"height": 213,
"collapsed": false,
"inherited": false,
"registry": "data/string/AdvancedFormat",
"dynamic_inputs": [
{
"name": "item0",
"type": "*"
},
{
"name": "item1",
"type": "*"
},
{
"name": "item2",
"type": "*"
},
{
"name": "item3",
"type": "*"
},
{
"name": "item4",
"type": "*"
}
],
"base_type": "core/DynamicSocketNodeBase"
},
"e2e099d2-f704-425b-82c2-5b7cfdf47b49": {
"title": "Emit Scene Status",
"id": "e2e099d2-f704-425b-82c2-5b7cfdf47b49",
"properties": {},
"x": 1912,
"y": 89,
"width": 143,
"height": 26,
"collapsed": false,
"inherited": false,
"registry": "event/EmitSceneStatus",
"base_type": "core/Node"
},
"aef5ffb9-835f-42c4-aec2-c320f43e57f7": {
"title": "Advanced Format",
"id": "aef5ffb9-835f-42c4-aec2-c320f43e57f7",
"properties": {
"template": "Update `{human_id}`:\n\n``` diff\n{diff_plain}\n```"
},
"x": 1092,
"y": 309,
"width": 210,
"height": 153,
"collapsed": true,
"inherited": false,
"registry": "data/string/AdvancedFormat",
"dynamic_inputs": [
{
"name": "item0",
"type": "*"
},
{
"name": "item1",
"type": "*"
}
],
"base_type": "core/DynamicSocketNodeBase"
},
"d16b01eb-a9eb-438b-8012-29cfc8285f09": {
"title": "Director Action Confirm",
"id": "d16b01eb-a9eb-438b-8012-29cfc8285f09",
"properties": {
"name": "update_context",
"description": "",
"raise_on_reject": true
},
"x": 1284,
"y": 233,
"width": 237,
"height": 146,
"collapsed": false,
"inherited": false,
"registry": "agents/director/chat/ActionConfirm",
"base_type": "core/Node"
},
"4d716619-394a-441c-94ac-f4b3ed800c10": {
"title": "AI Function Callback Metadata",
"id": "4d716619-394a-441c-94ac-f4b3ed800c10",
"properties": {
"instructions": "Make a direct value replacement update to a provided Context ID.\n\nNEVER use this to update character or world context. Leave it to the writers.\n\nIMPORTANT: You must only use this if both an extact Context ID and a new complete VERBATIM value have been provided to you in your instructions. Otherwise defer to the dedicated functions provided for the context type.\n\nYou CANNOT pass instructions to the value as this is a DIRECT VALUE REPLACEMENT.\n\nYou CANNOT use this to create or delete Context IDs, only update existing ones.\n\nThis can be used to quickly update:\n\n- Story Title via Context ID `story_configuration:title`\n- Story Description via Context ID `story_configuration:description`\n- Content Classification via Context ID `story_configuration:content_classification`",
"examples": [
{
"context_id": "character.attribute:Jessica.013f54400c82",
"value": "32"
},
{
"context_id": "story_configuration:title",
"value": "Infinity Quest 2"
}
]
},
"x": 2424,
"y": 183,
"width": 314,
"height": 82,
"collapsed": false,
"inherited": false,
"registry": "focal/Metadata",
"base_type": "core/Node"
}
},
"edges": {
"c62f076c-8e48-4a1a-ac50-e31ea4766895.value": [
"38961db6-7b4a-4ad1-a91a-1e8b151ee795.value"
],
"38961db6-7b4a-4ad1-a91a-1e8b151ee795.value": [
"6d188919-9f0e-4945-b9ff-d75ee92b0ce9.path"
],
"22020aa2-1867-40e5-9a7b-96e93f2945ed.value": [
"c8044776-d8a7-41b2-b800-374f0739a818.b",
"d16b01eb-a9eb-438b-8012-29cfc8285f09.state"
],
"2bec2758-fe44-468a-a9ec-73d236f3a09f.value": [
"4d716619-394a-441c-94ac-f4b3ed800c10.state"
],
"6d188919-9f0e-4945-b9ff-d75ee92b0ce9.context_id_item": [
"db7c5f98-b007-4187-a47d-26490c3219bc.context_id_item"
],
"6d188919-9f0e-4945-b9ff-d75ee92b0ce9.human_id": [
"8b71aa2a-3930-4c9a-ae81-590e65e66f56.item2",
"aef5ffb9-835f-42c4-aec2-c320f43e57f7.item0"
],
"6d188919-9f0e-4945-b9ff-d75ee92b0ce9.value": [
"c8044776-d8a7-41b2-b800-374f0739a818.a"
],
"c8044776-d8a7-41b2-b800-374f0739a818.diff_plain": [
"8b71aa2a-3930-4c9a-ae81-590e65e66f56.item3",
"aef5ffb9-835f-42c4-aec2-c320f43e57f7.item1"
],
"db7c5f98-b007-4187-a47d-26490c3219bc.context_id_item": [
"8b71aa2a-3930-4c9a-ae81-590e65e66f56.item4",
"e2e099d2-f704-425b-82c2-5b7cfdf47b49.state"
],
"db7c5f98-b007-4187-a47d-26490c3219bc.value": [
"8b71aa2a-3930-4c9a-ae81-590e65e66f56.item1"
],
"8b71aa2a-3930-4c9a-ae81-590e65e66f56.result": [
"2bec2758-fe44-468a-a9ec-73d236f3a09f.value"
],
"e2e099d2-f704-425b-82c2-5b7cfdf47b49.state": [
"8b71aa2a-3930-4c9a-ae81-590e65e66f56.item0"
],
"aef5ffb9-835f-42c4-aec2-c320f43e57f7.result": [
"d16b01eb-a9eb-438b-8012-29cfc8285f09.description"
],
"d16b01eb-a9eb-438b-8012-29cfc8285f09.accepted": [
"db7c5f98-b007-4187-a47d-26490c3219bc.state",
"db7c5f98-b007-4187-a47d-26490c3219bc.value"
]
},
"groups": [
{
"title": "Function",
"x": 1,
"y": -3,
"width": 2774,
"height": 512,
"color": "#b06634",
"font_size": 24,
"inherited": false
}
],
"comments": [],
"extends": null,
"base_type": "core/functions/Function",
"inputs": [],
"outputs": [
{
"id": "a068fd03-c1fa-49af-8d6f-1641333d2a9f",
"name": "fn",
"optional": false,
"group": null,
"socket_type": "function"
}
],
"module_properties": {},
"style": {
"title_color": "#573a2e",
"node_color": "#392f2c",
"icon": "F0295",
"auto_title": null,
"counterpart": null
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,426 @@
{
"title": "Director Action Summary",
"id": "f97a9e88-da71-4ec1-85ee-f933ebb7d977",
"properties": {},
"x": 0,
"y": 0,
"width": 200,
"height": 100,
"collapsed": false,
"inherited": false,
"registry": "agents/director/chat/directorActionSummary",
"nodes": {
"fcdccc00-2b00-46d0-9921-963a0e47936b": {
"title": "Argument",
"id": "fcdccc00-2b00-46d0-9921-963a0e47936b",
"properties": {
"name": "item",
"typ": "str"
},
"x": 26,
"y": -390,
"width": 210,
"height": 82,
"collapsed": false,
"inherited": false,
"registry": "core/functions/Argument",
"base_type": "core/Node"
},
"44ffdacc-cb9c-4085-bddd-190838617b38": {
"title": "RSwitch Advanced",
"id": "44ffdacc-cb9c-4085-bddd-190838617b38",
"properties": {},
"x": 600,
"y": -237,
"width": 196,
"height": 66,
"collapsed": false,
"inherited": false,
"registry": "core/RSwitchAdvanced",
"base_type": "core/Node"
},
"210b2e70-f910-425c-bed9-f94d2edaf498": {
"title": "Coallesce",
"id": "210b2e70-f910-425c-bed9-f94d2edaf498",
"properties": {},
"x": 830,
"y": -237,
"width": 140,
"height": 86,
"collapsed": false,
"inherited": false,
"registry": "core/Coallesce",
"base_type": "core/Node"
},
"1f71a345-11d0-4487-ba2e-d470347dc15b": {
"title": "Format",
"id": "1f71a345-11d0-4487-ba2e-d470347dc15b",
"properties": {},
"x": 1010,
"y": -297,
"width": 140,
"height": 46,
"collapsed": false,
"inherited": false,
"registry": "data/string/Format",
"base_type": "core/Node"
},
"7ee58b96-dbda-4f80-90ac-39555769c91d": {
"title": "Return",
"id": "7ee58b96-dbda-4f80-90ac-39555769c91d",
"properties": {},
"x": 1200,
"y": -277,
"width": 140,
"height": 26,
"collapsed": false,
"inherited": false,
"registry": "core/functions/Return",
"base_type": "core/Node"
},
"ef874d5a-3c3d-4542-aa40-fd036fef1426": {
"title": "DEF action_log",
"id": "ef874d5a-3c3d-4542-aa40-fd036fef1426",
"properties": {
"name": "action_log"
},
"x": 1380,
"y": -287,
"width": 210,
"height": 78,
"collapsed": false,
"inherited": false,
"registry": "core/functions/DefineFunction",
"base_type": "core/Node"
},
"3c69ec94-7756-4147-aa77-b90c7e5fc0ff": {
"title": "Failure Message",
"id": "3c69ec94-7756-4147-aa77-b90c7e5fc0ff",
"properties": {
"value": "Action `{name}` FAILED: {error}"
},
"x": 280,
"y": -207,
"width": 210,
"height": 58,
"collapsed": false,
"inherited": false,
"registry": "data/string/MakeText",
"base_type": "core/Node"
},
"744633b3-f82a-4884-b1f5-3f2b038e4b1a": {
"title": "Success Message",
"id": "744633b3-f82a-4884-b1f5-3f2b038e4b1a",
"properties": {
"value": "Action `{name}` SUCCESS: {result}"
},
"x": 275,
"y": -89,
"width": 210,
"height": 58,
"collapsed": false,
"inherited": false,
"registry": "data/string/MakeText",
"base_type": "core/Node"
},
"5e4a297f-651b-4c7f-960f-c016aaaf9509": {
"title": "Dict Collector",
"id": "5e4a297f-651b-4c7f-960f-c016aaaf9509",
"properties": {},
"x": 606,
"y": -407,
"width": 140,
"height": 121,
"collapsed": false,
"inherited": false,
"registry": "data/DictCollector",
"dynamic_inputs": [
{
"name": "item0",
"type": "*"
},
{
"name": "item1",
"type": "*"
},
{
"name": "item2",
"type": "*"
}
],
"base_type": "core/DynamicSocketNodeBase"
},
"c44db99b-f6c7-4960-9dab-bdc865032952": {
"title": "Unpack AI Function Call",
"id": "c44db99b-f6c7-4960-9dab-bdc865032952",
"properties": {},
"x": 266,
"y": -390,
"width": 230,
"height": 126,
"collapsed": false,
"inherited": false,
"registry": "focal/UnpackCall",
"base_type": "core/Node"
},
"caba09ec-eaad-400f-939d-771df167d5bf": {
"title": "FN action_log",
"id": "caba09ec-eaad-400f-939d-771df167d5bf",
"properties": {
"name": "action_log"
},
"x": 286,
"y": 136,
"width": 210,
"height": 78,
"collapsed": true,
"inherited": false,
"registry": "core/functions/GetFunction",
"base_type": "core/Node"
},
"66591f1f-41a3-4179-af88-7c0cd79b6076": {
"title": "true",
"id": "66591f1f-41a3-4179-af88-7c0cd79b6076",
"properties": {
"value": true
},
"x": 336,
"y": 76,
"width": 210,
"height": 58,
"collapsed": true,
"inherited": false,
"registry": "core/MakeBool",
"base_type": "core/Node"
},
"0a364053-70ba-4e78-b493-7c75455d6533": {
"title": "Call For Each",
"id": "0a364053-70ba-4e78-b493-7c75455d6533",
"properties": {
"copy_items": false,
"argument_name": "item"
},
"x": 506,
"y": 116,
"width": 210,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "core/functions/CallForEach",
"base_type": "core/Node"
},
"10696192-ac8d-4c41-aa5e-8ddb4a343b88": {
"title": "OUT summary",
"id": "10696192-ac8d-4c41-aa5e-8ddb4a343b88",
"properties": {
"output_type": "str",
"output_name": "summary",
"num": 0
},
"x": 1287,
"y": 199,
"width": 210,
"height": 106,
"collapsed": false,
"inherited": false,
"registry": "core/Output",
"base_type": "core/Node"
},
"4e416484-fd48-49ad-ae43-def93ff8b110": {
"title": "Join",
"id": "4e416484-fd48-49ad-ae43-def93ff8b110",
"properties": {
"delimiter": " \\n"
},
"x": 806,
"y": 126,
"width": 210,
"height": 78,
"collapsed": false,
"inherited": false,
"registry": "data/string/Join",
"base_type": "core/Node"
},
"6ed10692-eacf-49a9-8dc5-bef6cb54502f": {
"title": "RSwitch Advanced",
"id": "6ed10692-eacf-49a9-8dc5-bef6cb54502f",
"properties": {},
"x": 287,
"y": 249,
"width": 182,
"height": 66,
"collapsed": false,
"inherited": false,
"registry": "core/RSwitchAdvanced",
"base_type": "core/Node"
},
"997db282-2906-4796-bd98-56380a87e160": {
"title": "IN calls",
"id": "997db282-2906-4796-bd98-56380a87e160",
"properties": {
"input_type": "list",
"input_name": "calls",
"input_optional": false,
"input_group": "",
"num": 0
},
"x": 27,
"y": 109,
"width": 210,
"height": 154,
"collapsed": false,
"inherited": false,
"registry": "core/Input",
"base_type": "core/Node"
},
"f4052651-2d29-4e43-8303-0d8387cdfe7a": {
"title": "Advanced Format",
"id": "f4052651-2d29-4e43-8303-0d8387cdfe7a",
"properties": {
"template": "No action's were taken."
},
"x": 37,
"y": 389,
"width": 210,
"height": 113,
"collapsed": false,
"inherited": false,
"registry": "data/string/AdvancedFormat",
"dynamic_inputs": [],
"base_type": "core/DynamicSocketNodeBase"
},
"9a20c20e-4eb6-4c9d-9a3d-8ef2d69385f3": {
"title": "Coallesce",
"id": "9a20c20e-4eb6-4c9d-9a3d-8ef2d69385f3",
"properties": {},
"x": 1087,
"y": 239,
"width": 140,
"height": 86,
"collapsed": false,
"inherited": false,
"registry": "core/Coallesce",
"base_type": "core/Node"
},
"cfa63481-a7f1-4386-8115-c2347aa6101b": {
"title": "Module Style",
"id": "cfa63481-a7f1-4386-8115-c2347aa6101b",
"properties": {
"node_color": "#27233a",
"title_color": "#3d315b",
"auto_title": null,
"icon": "F09DE"
},
"x": 1400,
"y": -630,
"width": 210,
"height": 110,
"collapsed": false,
"inherited": false,
"registry": "util/ModuleStyle",
"base_type": "core/Node"
}
},
"edges": {
"fcdccc00-2b00-46d0-9921-963a0e47936b.value": [
"c44db99b-f6c7-4960-9dab-bdc865032952.call"
],
"44ffdacc-cb9c-4085-bddd-190838617b38.yes": [
"210b2e70-f910-425c-bed9-f94d2edaf498.a"
],
"44ffdacc-cb9c-4085-bddd-190838617b38.no": [
"210b2e70-f910-425c-bed9-f94d2edaf498.b"
],
"210b2e70-f910-425c-bed9-f94d2edaf498.value": [
"1f71a345-11d0-4487-ba2e-d470347dc15b.template"
],
"1f71a345-11d0-4487-ba2e-d470347dc15b.result": [
"7ee58b96-dbda-4f80-90ac-39555769c91d.value"
],
"7ee58b96-dbda-4f80-90ac-39555769c91d.value": [
"ef874d5a-3c3d-4542-aa40-fd036fef1426.nodes"
],
"3c69ec94-7756-4147-aa77-b90c7e5fc0ff.value": [
"44ffdacc-cb9c-4085-bddd-190838617b38.yes"
],
"744633b3-f82a-4884-b1f5-3f2b038e4b1a.value": [
"44ffdacc-cb9c-4085-bddd-190838617b38.no"
],
"5e4a297f-651b-4c7f-960f-c016aaaf9509.dict": [
"1f71a345-11d0-4487-ba2e-d470347dc15b.variables"
],
"c44db99b-f6c7-4960-9dab-bdc865032952.name": [
"5e4a297f-651b-4c7f-960f-c016aaaf9509.item0"
],
"c44db99b-f6c7-4960-9dab-bdc865032952.result": [
"5e4a297f-651b-4c7f-960f-c016aaaf9509.item1"
],
"c44db99b-f6c7-4960-9dab-bdc865032952.error": [
"44ffdacc-cb9c-4085-bddd-190838617b38.check",
"5e4a297f-651b-4c7f-960f-c016aaaf9509.item2"
],
"caba09ec-eaad-400f-939d-771df167d5bf.fn": [
"0a364053-70ba-4e78-b493-7c75455d6533.fn"
],
"66591f1f-41a3-4179-af88-7c0cd79b6076.value": [
"0a364053-70ba-4e78-b493-7c75455d6533.state"
],
"0a364053-70ba-4e78-b493-7c75455d6533.results": [
"4e416484-fd48-49ad-ae43-def93ff8b110.strings"
],
"4e416484-fd48-49ad-ae43-def93ff8b110.result": [
"9a20c20e-4eb6-4c9d-9a3d-8ef2d69385f3.a"
],
"6ed10692-eacf-49a9-8dc5-bef6cb54502f.yes": [
"0a364053-70ba-4e78-b493-7c75455d6533.items"
],
"6ed10692-eacf-49a9-8dc5-bef6cb54502f.no": [
"9a20c20e-4eb6-4c9d-9a3d-8ef2d69385f3.b"
],
"997db282-2906-4796-bd98-56380a87e160.value": [
"6ed10692-eacf-49a9-8dc5-bef6cb54502f.check",
"6ed10692-eacf-49a9-8dc5-bef6cb54502f.yes"
],
"f4052651-2d29-4e43-8303-0d8387cdfe7a.result": [
"6ed10692-eacf-49a9-8dc5-bef6cb54502f.no"
],
"9a20c20e-4eb6-4c9d-9a3d-8ef2d69385f3.value": [
"10696192-ac8d-4c41-aa5e-8ddb4a343b88.value"
]
},
"groups": [
{
"title": "Group",
"x": 2,
"y": -482,
"width": 1614,
"height": 476,
"color": "#b06634",
"font_size": 24,
"inherited": false
},
{
"title": "Main",
"x": 1,
"y": -4,
"width": 1609,
"height": 563,
"color": "#3f789e",
"font_size": 24,
"inherited": false
}
],
"comments": [],
"extends": null,
"base_type": "core/Graph",
"inputs": [],
"outputs": [],
"module_properties": {},
"style": {
"title_color": "#3d315b",
"node_color": "#27233a",
"icon": "F09DE",
"auto_title": null,
"counterpart": null
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,258 @@
{
"title": "Director Action Update Gamestate",
"id": "59a62e49-cd1f-4ce8-80db-ed1a24501ba5",
"properties": {
"name": "update_gamestate",
"description": "Instruct another agent to make updates to any game state variables. You should query for relevant game state variables BEFORE using this.\n\nIf you're changing existing game states provide the FULL path to the final key.\n\nIMPORTANT: Not all stories / experiences are games. Only use this if explicitly confirmed by the user or if the current scene type allows it.",
"instructions": "Make updates to the game state variables.",
"example_json": "[\n {\n \"instructions\": \"Set up base attributes of health and stamina for all characters. Lets do this keyed to the character name and for all current characters: \\\"Mary\\\" and \\\"John\\\". Defaults should should like `{ \\\"health\\\": 100, \\\"stamina\\\": 100 }`\"\n },\n {\n \"instructions\": \"Set John's health to 50%\",\n },\n {\n \"instructions\": \"We need tomaintain a numeric representation of Mary's mana. Lets add a new variable called 'mana' to the game state for her character.\"\n }\n]"
},
"x": 0,
"y": 0,
"width": 200,
"height": 100,
"collapsed": false,
"inherited": false,
"registry": "agents/director/chat/directorActionUpdateGamestate",
"nodes": {
"25b43bed-e4bf-45c0-87c7-72c5785c1d62": {
"title": "Validate Value Is Set",
"id": "25b43bed-e4bf-45c0-87c7-72c5785c1d62",
"properties": {
"error_message": "`instructions` is a required argument.",
"blank_string_is_unset": true
},
"x": 286,
"y": -161,
"width": 210,
"height": 102,
"collapsed": false,
"inherited": false,
"registry": "validation/ValidateValueIsSet",
"base_type": "core/Node"
},
"76cdeb2c-20c0-413b-a6d3-642ba59ab8b3": {
"title": "SET local.instructions",
"id": "76cdeb2c-20c0-413b-a6d3-642ba59ab8b3",
"properties": {
"name": "instructions",
"scope": "local"
},
"x": 556,
"y": -151,
"width": 210,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "state/SetState",
"base_type": "core/Node"
},
"97025c52-ac1d-41e5-8ec6-8ea1a7fe635f": {
"title": "Stage 0",
"id": "97025c52-ac1d-41e5-8ec6-8ea1a7fe635f",
"properties": {
"stage": 0
},
"x": 806,
"y": -151,
"width": 210,
"height": 118,
"collapsed": false,
"inherited": false,
"registry": "core/Stage",
"base_type": "core/Node"
},
"fa4a84ad-a696-4ede-9471-fbef8c1c98ee": {
"title": "GET local.instructions",
"id": "fa4a84ad-a696-4ede-9471-fbef8c1c98ee",
"properties": {
"name": "instructions",
"scope": "local"
},
"x": 26,
"y": 121,
"width": 210,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "state/GetState",
"base_type": "core/Node"
},
"75a6f3c1-21a5-47cc-ac25-1627b5a2d4ac": {
"title": "Instructions",
"id": "75a6f3c1-21a5-47cc-ac25-1627b5a2d4ac",
"properties": {
"template": "Use codeblocks containing data structures to propose sequential updates to the existing gamestate structure to fulfill the following task.\n\nTASK: {instructions}\n\nBegin by planning your actions, then provide the necessary code blocks."
},
"x": 286,
"y": 121,
"width": 210,
"height": 133,
"collapsed": false,
"inherited": false,
"registry": "data/string/AdvancedFormat",
"dynamic_inputs": [
{
"name": "item0",
"type": "*"
}
],
"base_type": "core/DynamicSocketNodeBase"
},
"643e7707-9689-41c2-9053-b6370c7e5c14": {
"title": "Instruct Gamestate Updates",
"id": "643e7707-9689-41c2-9053-b6370c7e5c14",
"properties": {},
"x": 566,
"y": 141,
"width": 218,
"height": 66,
"collapsed": false,
"inherited": false,
"registry": "agernts/director/chat/instructGamestateUpdates",
"base_type": "core/Graph"
},
"516270c5-e694-44d7-9ac2-960461ee92b2": {
"title": "Return",
"id": "516270c5-e694-44d7-9ac2-960461ee92b2",
"properties": {},
"x": 1249,
"y": 148,
"width": 140,
"height": 26,
"collapsed": false,
"inherited": false,
"registry": "core/functions/Return",
"base_type": "core/Node"
},
"64136cbd-4b3b-4586-9122-4fae36374af8": {
"title": "Advanced Format",
"id": "64136cbd-4b3b-4586-9122-4fae36374af8",
"properties": {
"template": "Applied the following gamestate updates:\n\n```\n{updates}\n```"
},
"x": 926,
"y": 151,
"width": 210,
"height": 153,
"collapsed": false,
"inherited": false,
"registry": "data/string/AdvancedFormat",
"dynamic_inputs": [
{
"name": "item0",
"type": "*"
},
{
"name": "item1",
"type": "*"
}
],
"base_type": "core/DynamicSocketNodeBase"
},
"0404af9c-3a1e-4535-b8bc-5e8257f95d20": {
"title": "true",
"id": "0404af9c-3a1e-4535-b8bc-5e8257f95d20",
"properties": {
"value": true
},
"x": 406,
"y": 81,
"width": 210,
"height": 58,
"collapsed": true,
"inherited": false,
"registry": "core/MakeBool",
"base_type": "core/Node"
},
"90bd1c80-9a8e-404c-a32f-f17c314ddb65": {
"title": "instructions",
"id": "90bd1c80-9a8e-404c-a32f-f17c314ddb65",
"properties": {
"name": "instructions",
"typ": "str",
"instructions": "Your precise instructions on what changes to make to the game state JSON object literal. You can add / update / remove keys. Keys need to be specified as absolute paths inside the structure."
},
"x": 26,
"y": -171,
"width": 210,
"height": 106,
"collapsed": false,
"inherited": false,
"registry": "agents/director/chat/ActionArgument",
"base_type": "core/Node"
}
},
"edges": {
"25b43bed-e4bf-45c0-87c7-72c5785c1d62.value": [
"76cdeb2c-20c0-413b-a6d3-642ba59ab8b3.value"
],
"76cdeb2c-20c0-413b-a6d3-642ba59ab8b3.value": [
"97025c52-ac1d-41e5-8ec6-8ea1a7fe635f.state"
],
"fa4a84ad-a696-4ede-9471-fbef8c1c98ee.value": [
"75a6f3c1-21a5-47cc-ac25-1627b5a2d4ac.item0"
],
"75a6f3c1-21a5-47cc-ac25-1627b5a2d4ac.result": [
"643e7707-9689-41c2-9053-b6370c7e5c14.instructions"
],
"643e7707-9689-41c2-9053-b6370c7e5c14.state": [
"64136cbd-4b3b-4586-9122-4fae36374af8.item0"
],
"643e7707-9689-41c2-9053-b6370c7e5c14.updates": [
"64136cbd-4b3b-4586-9122-4fae36374af8.item1"
],
"64136cbd-4b3b-4586-9122-4fae36374af8.result": [
"516270c5-e694-44d7-9ac2-960461ee92b2.value"
],
"0404af9c-3a1e-4535-b8bc-5e8257f95d20.value": [
"643e7707-9689-41c2-9053-b6370c7e5c14.state"
],
"90bd1c80-9a8e-404c-a32f-f17c314ddb65.value": [
"25b43bed-e4bf-45c0-87c7-72c5785c1d62.value"
]
},
"groups": [
{
"title": "Validation",
"x": 1,
"y": -246,
"width": 1050,
"height": 242,
"color": "#b58b2a",
"font_size": 24,
"inherited": false
},
{
"title": "Process",
"x": 1,
"y": 0,
"width": 1413,
"height": 328,
"color": "#3f789e",
"font_size": 24,
"inherited": false
}
],
"comments": [],
"extends": null,
"base_type": "agents/director/DirectorChatAction",
"inputs": [],
"outputs": [
{
"id": "00213835-5a0f-4aab-ab0a-af83646336f8",
"name": "fn",
"optional": false,
"group": null,
"socket_type": "function"
}
],
"module_properties": {},
"style": {
"title_color": "#573a2e",
"node_color": "#392f2c",
"icon": "F0295",
"auto_title": null,
"counterpart": null
}
}

View File

@@ -0,0 +1,250 @@
{
"title": "Director Agent Retrieve Context",
"id": "0f3aa8ec-122d-4e56-bdd0-363da9fcfc05",
"properties": {
"name": "retrieve_context",
"description": "Instruct another agent to retrieve the complete content of a specific source context ID for you. \n\nOnly use this if you have obtained such context ids. They are always formatted like this: `{context_type}:{context_id}`\n\nIMPORTANT: THIS ALWAYS REQUIRES YOU TO PASS AT LEAST ONE KNOWN, EXISTING CONTEXT ID. IF YOU DO NOT HAVE ONE DO NOT USE THIS ACTION.",
"instructions": "Use an exact source context ID to retrieve the content of the source.\n\nSource context IDs are always formatted like this: `{context_type}:{context_id}`",
"example_json": "[\n {\n \"context_id\": \"context_type:context_id\"\n }\n]"
},
"x": 0,
"y": 0,
"width": 200,
"height": 100,
"collapsed": false,
"inherited": false,
"registry": "agents/director/chat/directorAgentRetrieveContext",
"nodes": {
"f99df00a-da22-4efa-8ebc-acd6e590fc64": {
"title": "Validate Value Is Set",
"id": "f99df00a-da22-4efa-8ebc-acd6e590fc64",
"properties": {
"error_message": "`context_id` is required",
"blank_string_is_unset": true
},
"x": 283,
"y": 28,
"width": 210,
"height": 102,
"collapsed": false,
"inherited": false,
"registry": "validation/ValidateValueIsSet",
"base_type": "core/Node"
},
"92803a25-b624-4289-a6ef-87dcd0fc447d": {
"title": "Validate Context ID Item",
"id": "92803a25-b624-4289-a6ef-87dcd0fc447d",
"properties": {
"error_message": ""
},
"x": 528,
"y": 42,
"width": 245,
"height": 98,
"collapsed": false,
"inherited": false,
"registry": "validation/ValidateContextIDItem",
"base_type": "core/Node"
},
"9ee58437-7ccb-4b40-ac61-9a2434e85223": {
"title": "GET local.context_id_item",
"id": "9ee58437-7ccb-4b40-ac61-9a2434e85223",
"properties": {
"name": "context_id_item",
"scope": "local"
},
"x": 33,
"y": 292,
"width": 210,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "state/GetState",
"base_type": "core/Node"
},
"f94ca43f-5d0d-4edf-85ef-93010ae67732": {
"title": "Context ID Get Value",
"id": "f94ca43f-5d0d-4edf-85ef-93010ae67732",
"properties": {},
"x": 270,
"y": 360,
"width": 262,
"height": 46,
"collapsed": false,
"inherited": false,
"registry": "context_id/ContextIDGetValue",
"base_type": "core/Node"
},
"9934d9c8-55a1-4ffb-ac7a-79a1bfaee5aa": {
"title": "Watch",
"id": "9934d9c8-55a1-4ffb-ac7a-79a1bfaee5aa",
"properties": {},
"x": 860,
"y": 390,
"width": 140,
"height": 26,
"collapsed": false,
"inherited": false,
"registry": "core/Watch",
"base_type": "core/Node"
},
"51fc6efe-df09-4e32-9066-ba9163f8a555": {
"title": "Return",
"id": "51fc6efe-df09-4e32-9066-ba9163f8a555",
"properties": {},
"x": 1050,
"y": 390,
"width": 140,
"height": 26,
"collapsed": false,
"inherited": false,
"registry": "core/functions/Return",
"base_type": "core/Node"
},
"c3e1908f-3f66-4ac3-8619-409107dfe04e": {
"title": "Advanced Format",
"id": "c3e1908f-3f66-4ac3-8619-409107dfe04e",
"properties": {
"template": "### {context_id_item.human_id}\nContext ID: `{context_id_item.context_id}`\n\n```\n{value}\n```"
},
"x": 580,
"y": 371,
"width": 210,
"height": 153,
"collapsed": false,
"inherited": false,
"registry": "data/string/AdvancedFormat",
"dynamic_inputs": [
{
"name": "item0",
"type": "*"
},
{
"name": "item1",
"type": "*"
}
],
"base_type": "core/DynamicSocketNodeBase"
},
"fa60dcd2-97df-474c-8e78-fd0ded483ee7": {
"title": "SET local.context_id_item",
"id": "fa60dcd2-97df-474c-8e78-fd0ded483ee7",
"properties": {
"name": "context_id_item",
"scope": "local"
},
"x": 811,
"y": 46,
"width": 227,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "state/SetState",
"base_type": "core/Node"
},
"59c92079-d971-486b-b53a-0c80194eec50": {
"title": "Stage",
"id": "59c92079-d971-486b-b53a-0c80194eec50",
"properties": {
"stage": 0
},
"x": 1071,
"y": 66,
"width": 210,
"height": 118,
"collapsed": false,
"inherited": false,
"registry": "core/Stage",
"base_type": "core/Node"
},
"15f2e707-fe7f-4c68-8227-97af24641a32": {
"title": "Director Action Argument",
"id": "15f2e707-fe7f-4c68-8227-97af24641a32",
"properties": {
"name": "context_id",
"typ": "str",
"instructions": "The exact source context ID.\n\nSource context IDs are always formatted like this: `{context_type}:{context_id}`"
},
"x": 33,
"y": 18,
"width": 210,
"height": 106,
"collapsed": false,
"inherited": false,
"registry": "agents/director/chat/ActionArgument",
"base_type": "core/Node"
}
},
"edges": {
"f99df00a-da22-4efa-8ebc-acd6e590fc64.value": [
"92803a25-b624-4289-a6ef-87dcd0fc447d.value"
],
"92803a25-b624-4289-a6ef-87dcd0fc447d.context_id_item": [
"fa60dcd2-97df-474c-8e78-fd0ded483ee7.value"
],
"9ee58437-7ccb-4b40-ac61-9a2434e85223.value": [
"f94ca43f-5d0d-4edf-85ef-93010ae67732.context_id_item"
],
"f94ca43f-5d0d-4edf-85ef-93010ae67732.context_id_item": [
"c3e1908f-3f66-4ac3-8619-409107dfe04e.item0"
],
"f94ca43f-5d0d-4edf-85ef-93010ae67732.value": [
"c3e1908f-3f66-4ac3-8619-409107dfe04e.item1"
],
"9934d9c8-55a1-4ffb-ac7a-79a1bfaee5aa.value": [
"51fc6efe-df09-4e32-9066-ba9163f8a555.value"
],
"c3e1908f-3f66-4ac3-8619-409107dfe04e.result": [
"9934d9c8-55a1-4ffb-ac7a-79a1bfaee5aa.value"
],
"fa60dcd2-97df-474c-8e78-fd0ded483ee7.value": [
"59c92079-d971-486b-b53a-0c80194eec50.state_b"
],
"15f2e707-fe7f-4c68-8227-97af24641a32.value": [
"f99df00a-da22-4efa-8ebc-acd6e590fc64.value"
]
},
"groups": [
{
"title": "Input Validation",
"x": 8,
"y": -62,
"width": 1298,
"height": 271,
"color": "#b58b2a",
"font_size": 24,
"inherited": false
},
{
"title": "Return source",
"x": 8,
"y": 212,
"width": 1288,
"height": 459,
"color": "#3f789e",
"font_size": 24,
"inherited": false
}
],
"comments": [],
"extends": null,
"base_type": "agents/director/DirectorChatAction",
"inputs": [],
"outputs": [
{
"id": "1e38e35a-3e56-460c-b6bf-63efc5078f77",
"name": "fn",
"optional": false,
"group": null,
"socket_type": "function"
}
],
"module_properties": {},
"style": {
"title_color": "#573a2e",
"node_color": "#392f2c",
"icon": "F0295",
"auto_title": null,
"counterpart": null
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,782 @@
{
"title": "Instruct Character Creation",
"id": "324867c5-5e9a-47cb-a797-27236021f744",
"properties": {},
"x": 0,
"y": 0,
"width": 200,
"height": 100,
"collapsed": false,
"inherited": false,
"registry": "agents/director/chat/instructCharacterCreation",
"nodes": {
"fe95c78d-2a24-4c84-8509-a6024443f2a3": {
"title": "Persist Character",
"id": "fe95c78d-2a24-4c84-8509-a6024443f2a3",
"properties": {
"determine_name": true
},
"x": 322,
"y": 70,
"width": 210,
"height": 118,
"collapsed": false,
"inherited": false,
"registry": "agents/director/PersistCharacter",
"base_type": "core/Node"
},
"dd7a7e8d-445e-4ba4-8395-2433dc479701": {
"title": "RSwitch",
"id": "dd7a7e8d-445e-4ba4-8395-2433dc479701",
"properties": {},
"x": 545,
"y": 393,
"width": 140,
"height": 66,
"collapsed": false,
"inherited": false,
"registry": "core/RSwitch",
"base_type": "core/Node"
},
"30e158e5-504a-4604-863e-ee073945e54b": {
"title": "Deactivate Character",
"id": "30e158e5-504a-4604-863e-ee073945e54b",
"properties": {},
"x": 735,
"y": 433,
"width": 168,
"height": 26,
"collapsed": false,
"inherited": false,
"registry": "scene/DeactivateCharacter",
"base_type": "core/Node"
},
"b8ef5821-b2af-4ed0-916e-51f43fccba54": {
"title": "Input Socket",
"id": "b8ef5821-b2af-4ed0-916e-51f43fccba54",
"properties": {
"input_type": "any",
"input_name": "state",
"input_optional": false,
"input_group": "",
"num": 0
},
"x": 7,
"y": -1007,
"width": 210,
"height": 154,
"collapsed": false,
"inherited": false,
"registry": "core/Input",
"base_type": "core/Node"
},
"3b0e09ba-a3eb-488b-b8a5-532bfc14e2e2": {
"title": "active",
"id": "3b0e09ba-a3eb-488b-b8a5-532bfc14e2e2",
"properties": {},
"x": 363,
"y": 306,
"width": 140,
"height": 26,
"collapsed": false,
"inherited": false,
"registry": "core/Watch",
"base_type": "core/Node"
},
"29f83307-c9b9-48c7-bf74-b04dba05397f": {
"title": "AND Router",
"id": "29f83307-c9b9-48c7-bf74-b04dba05397f",
"properties": {},
"x": 531,
"y": 604,
"width": 140,
"height": 106,
"collapsed": false,
"inherited": false,
"registry": "core/ANDRouter",
"base_type": "core/Node"
},
"90a2763a-32c3-4aa9-9c88-d803a4e4329b": {
"title": "IN active",
"id": "90a2763a-32c3-4aa9-9c88-d803a4e4329b",
"properties": {
"input_type": "bool",
"input_name": "active",
"input_optional": false,
"input_group": "",
"num": 2
},
"x": 5,
"y": -540,
"width": 210,
"height": 154,
"collapsed": false,
"inherited": false,
"registry": "core/Input",
"base_type": "core/Node"
},
"302909ac-3c34-4690-a69d-dcee2bba6905": {
"title": "IN narrate_instructions",
"id": "302909ac-3c34-4690-a69d-dcee2bba6905",
"properties": {
"input_type": "str",
"input_name": "narrate_instructions",
"input_optional": false,
"input_group": "",
"num": 3
},
"x": 9,
"y": -292,
"width": 265,
"height": 154,
"collapsed": false,
"inherited": false,
"registry": "core/Input",
"base_type": "core/Node"
},
"7eee8c68-8f78-499a-898d-2728429a0e01": {
"title": "GET local.narrate_instructions",
"id": "7eee8c68-8f78-499a-898d-2728429a0e01",
"properties": {
"name": "narrate_instructions",
"scope": "local"
},
"x": 8,
"y": 613,
"width": 252,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "state/GetState",
"base_type": "core/Node"
},
"05e031c6-e9e4-414e-bbcd-aa338bae1d3e": {
"title": "GET local.active",
"id": "05e031c6-e9e4-414e-bbcd-aa338bae1d3e",
"properties": {
"name": "active",
"scope": "local"
},
"x": 18,
"y": 333,
"width": 210,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "state/GetState",
"base_type": "core/Node"
},
"146b4f6d-248a-421a-85bd-5c3f86de67aa": {
"title": "Generate Character Entry Narration",
"id": "146b4f6d-248a-421a-85bd-5c3f86de67aa",
"properties": {},
"x": 784,
"y": 872,
"width": 286,
"height": 66,
"collapsed": false,
"inherited": false,
"registry": "agents/narrator/GenerateCharacterEntryNarration",
"base_type": "core/Node"
},
"fe3b68bd-6853-439d-882b-770db12b6ccd": {
"title": "Push History",
"id": "fe3b68bd-6853-439d-882b-770db12b6ccd",
"properties": {
"emit_message": true
},
"x": 1194,
"y": 882,
"width": 210,
"height": 58,
"collapsed": false,
"inherited": false,
"registry": "scene/history/Push",
"base_type": "core/Node"
},
"1a89e3bb-bc71-46b1-8c3a-1072c07f820d": {
"title": "SET local.character",
"id": "1a89e3bb-bc71-46b1-8c3a-1072c07f820d",
"properties": {
"name": "character",
"scope": "local"
},
"x": 568,
"y": 70,
"width": 210,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "state/SetState",
"base_type": "core/Node"
},
"440d5bef-4023-4897-a1a1-149c5af3dbd3": {
"title": "Stage 2",
"id": "440d5bef-4023-4897-a1a1-149c5af3dbd3",
"properties": {
"stage": 2
},
"x": 1484,
"y": 492,
"width": 210,
"height": 118,
"collapsed": false,
"inherited": false,
"registry": "core/Stage",
"base_type": "core/Node"
},
"53da2fa3-4375-4d04-88d6-0f54b0a0d9ef": {
"title": "true",
"id": "53da2fa3-4375-4d04-88d6-0f54b0a0d9ef",
"properties": {
"value": true
},
"x": 168,
"y": -20,
"width": 210,
"height": 58,
"collapsed": true,
"inherited": false,
"registry": "core/MakeBool",
"base_type": "core/Node"
},
"7909b9ac-e61e-4b4b-844f-782ec9de05fd": {
"title": "GET local.character",
"id": "7909b9ac-e61e-4b4b-844f-782ec9de05fd",
"properties": {
"name": "character",
"scope": "local"
},
"x": 26,
"y": 869,
"width": 210,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "state/GetState",
"base_type": "core/Node"
},
"0cf22c95-ef4b-4199-b5ef-d364acb36050": {
"title": "Output Socket",
"id": "0cf22c95-ef4b-4199-b5ef-d364acb36050",
"properties": {
"output_type": "character",
"output_name": "character",
"num": 4
},
"x": 1166,
"y": 1143,
"width": 210,
"height": 106,
"collapsed": false,
"inherited": false,
"registry": "core/Output",
"base_type": "core/Node"
},
"307ef2f9-2ddc-4dbb-a916-f3eefc0239db": {
"title": "GET local.character",
"id": "307ef2f9-2ddc-4dbb-a916-f3eefc0239db",
"properties": {
"name": "character",
"scope": "local"
},
"x": 4,
"y": 1126,
"width": 210,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "state/GetState",
"base_type": "core/Node"
},
"cd3043d0-a852-4a1f-b22c-2defc600a50a": {
"title": "Output Socket",
"id": "cd3043d0-a852-4a1f-b22c-2defc600a50a",
"properties": {
"output_type": "str",
"output_name": "summary",
"num": 5
},
"x": 1183,
"y": 1353,
"width": 210,
"height": 106,
"collapsed": false,
"inherited": false,
"registry": "core/Output",
"base_type": "core/Node"
},
"56b7196a-1f22-4882-b8ae-f987936ff056": {
"title": "Get Character Description",
"id": "56b7196a-1f22-4882-b8ae-f987936ff056",
"properties": {},
"x": 293,
"y": 1293,
"width": 210,
"height": 46,
"collapsed": false,
"inherited": false,
"registry": "scene/GetCharacterDescription",
"base_type": "core/Node"
},
"ab198058-35a6-4796-b713-4f3678561cb5": {
"title": "Excerpt",
"id": "ab198058-35a6-4796-b713-4f3678561cb5",
"properties": {
"length": 256,
"add_ellipsis": true
},
"x": 544,
"y": 1419,
"width": 210,
"height": 82,
"collapsed": false,
"inherited": false,
"registry": "data/string/Excerpt",
"base_type": "core/Node"
},
"db3dbe65-087d-45f3-841e-28bc2928a4ff": {
"title": "Advanced Format",
"id": "db3dbe65-087d-45f3-841e-28bc2928a4ff",
"properties": {
"template": "Character Created: `{character.name}`\nDescription: \n\n```\n{result}\n```"
},
"x": 844,
"y": 1339,
"width": 210,
"height": 153,
"collapsed": false,
"inherited": false,
"registry": "data/string/AdvancedFormat",
"dynamic_inputs": [
{
"name": "item0",
"type": "*"
},
{
"name": "item1",
"type": "*"
}
],
"base_type": "core/DynamicSocketNodeBase"
},
"ea0d219e-b34b-4485-87a2-945fc513b314": {
"title": "OUT state",
"id": "ea0d219e-b34b-4485-87a2-945fc513b314",
"properties": {
"output_type": "any",
"output_name": "state",
"num": 0
},
"x": 1872,
"y": -1004,
"width": 210,
"height": 106,
"collapsed": false,
"inherited": false,
"registry": "core/Output",
"base_type": "core/Node"
},
"0edfb297-c55b-48eb-b261-2e3fac66430b": {
"title": "IN instructions",
"id": "0edfb297-c55b-48eb-b261-2e3fac66430b",
"properties": {
"input_type": "str",
"input_name": "instructions",
"input_optional": false,
"input_group": "",
"num": 1
},
"x": 10,
"y": -763,
"width": 210,
"height": 154,
"collapsed": false,
"inherited": false,
"registry": "core/Input",
"base_type": "core/Node"
},
"b1b25e45-5dac-4b14-9494-6c0fe640926b": {
"title": "Validate Value Is Set",
"id": "b1b25e45-5dac-4b14-9494-6c0fe640926b",
"properties": {
"error_message": "instructions are required.",
"blank_string_is_unset": true
},
"x": 311,
"y": -895,
"width": 216,
"height": 102,
"collapsed": false,
"inherited": false,
"registry": "validation/ValidateValueIsSet",
"base_type": "core/Node"
},
"555836b5-fc4b-4d30-a408-dfe3ed6dacb4": {
"title": "OUT narrate_instructions",
"id": "555836b5-fc4b-4d30-a408-dfe3ed6dacb4",
"properties": {
"output_type": "str",
"output_name": "narrate_instructions",
"num": 3
},
"x": 1861,
"y": -235,
"width": 210,
"height": 106,
"collapsed": false,
"inherited": false,
"registry": "core/Output",
"base_type": "core/Node"
},
"cb1f6271-309c-4d44-ba3a-052353626752": {
"title": "OUT active",
"id": "cb1f6271-309c-4d44-ba3a-052353626752",
"properties": {
"output_type": "bool",
"output_name": "active",
"num": 2
},
"x": 1871,
"y": -505,
"width": 210,
"height": 106,
"collapsed": false,
"inherited": false,
"registry": "core/Output",
"base_type": "core/Node"
},
"60b047db-3570-42f8-9c5a-36dfc1f4424f": {
"title": "OUT instructions",
"id": "60b047db-3570-42f8-9c5a-36dfc1f4424f",
"properties": {
"output_type": "str",
"output_name": "instructions",
"num": 1
},
"x": 1871,
"y": -745,
"width": 210,
"height": 106,
"collapsed": false,
"inherited": false,
"registry": "core/Output",
"base_type": "core/Node"
},
"55177ca7-4999-466e-8544-82da9a8af7da": {
"title": "Stage -1",
"id": "55177ca7-4999-466e-8544-82da9a8af7da",
"properties": {
"stage": -1
},
"x": 1531,
"y": -525,
"width": 210,
"height": 118,
"collapsed": false,
"inherited": false,
"registry": "core/Stage",
"base_type": "core/Node"
},
"bc919dfb-39c9-4eab-a452-fdb49f66e4c8": {
"title": "SET local.instructions",
"id": "bc919dfb-39c9-4eab-a452-fdb49f66e4c8",
"properties": {
"name": "instructions",
"scope": "local"
},
"x": 601,
"y": -905,
"width": 210,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "state/SetState",
"base_type": "core/Node"
},
"8aa0d95f-300b-4b73-9529-bd708512fd8f": {
"title": "SET local.instructions",
"id": "8aa0d95f-300b-4b73-9529-bd708512fd8f",
"properties": {
"name": "active",
"scope": "local"
},
"x": 461,
"y": -545,
"width": 210,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "state/SetState",
"base_type": "core/Node"
},
"fe99b452-e260-4dc8-a8eb-6d6de1cb8d0d": {
"title": "SET local.instructions",
"id": "fe99b452-e260-4dc8-a8eb-6d6de1cb8d0d",
"properties": {
"name": "narrate_instructions",
"scope": "local"
},
"x": 461,
"y": -275,
"width": 210,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "state/SetState",
"base_type": "core/Node"
},
"b456bbbb-47b2-4a51-b8d9-210f919337a4": {
"title": "Jinja2 Format",
"id": "b456bbbb-47b2-4a51-b8d9-210f919337a4",
"properties": {
"template": "### Create new character\n\n#### Creation instructions\n```\n{{ instructions }}\n```\n\n{% if narrate_instructions %}\n#### Narrate character entry\n```\n{{ narrate_instructions }}\n```\n{% endif %}\n\n**Active in scene**: {{ active }}"
},
"x": 871,
"y": -725,
"width": 210,
"height": 173,
"collapsed": false,
"inherited": false,
"registry": "prompt/Jinja2Format",
"dynamic_inputs": [
{
"name": "item0",
"type": "*"
},
{
"name": "item1",
"type": "*"
},
{
"name": "item2",
"type": "*"
}
],
"base_type": "core/DynamicSocketNodeBase"
},
"c049bcad-7006-47f5-bc10-1aa191571bd8": {
"title": "GET local.instructions",
"id": "c049bcad-7006-47f5-bc10-1aa191571bd8",
"properties": {
"name": "instructions",
"scope": "local"
},
"x": 4,
"y": 61,
"width": 210,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "state/GetState",
"base_type": "core/Node"
},
"b0e1848b-f6f6-42fa-97c8-f0e8b87b8b4c": {
"title": "Stage 1",
"id": "b0e1848b-f6f6-42fa-97c8-f0e8b87b8b4c",
"properties": {
"stage": 1
},
"x": 896,
"y": 79,
"width": 210,
"height": 118,
"collapsed": false,
"inherited": false,
"registry": "core/Stage",
"base_type": "core/Node"
},
"28125cd1-a285-430a-9582-e145ec6cecd0": {
"title": "Module Style",
"id": "28125cd1-a285-430a-9582-e145ec6cecd0",
"properties": {
"node_color": "#392c34",
"title_color": "#572e44",
"auto_title": null,
"icon": "F1719"
},
"x": 2141,
"y": -1005,
"width": 210,
"height": 110,
"collapsed": false,
"inherited": false,
"registry": "util/ModuleStyle",
"base_type": "core/Node"
},
"e4851859-59f4-4004-8e5c-4cdc4fb3064d": {
"title": "Director Action Confirm",
"id": "e4851859-59f4-4004-8e5c-4cdc4fb3064d",
"properties": {
"name": "create_character",
"description": "",
"raise_on_reject": true
},
"x": 1161,
"y": -885,
"width": 237,
"height": 146,
"collapsed": false,
"inherited": false,
"registry": "agents/director/chat/ActionConfirm",
"base_type": "core/Node"
}
},
"edges": {
"fe95c78d-2a24-4c84-8509-a6024443f2a3.character": [
"1a89e3bb-bc71-46b1-8c3a-1072c07f820d.value"
],
"dd7a7e8d-445e-4ba4-8395-2433dc479701.value": [
"30e158e5-504a-4604-863e-ee073945e54b.character"
],
"30e158e5-504a-4604-863e-ee073945e54b.character": [
"440d5bef-4023-4897-a1a1-149c5af3dbd3.state"
],
"b8ef5821-b2af-4ed0-916e-51f43fccba54.value": [
"ea0d219e-b34b-4485-87a2-945fc513b314.value"
],
"3b0e09ba-a3eb-488b-b8a5-532bfc14e2e2.value": [
"dd7a7e8d-445e-4ba4-8395-2433dc479701.check"
],
"29f83307-c9b9-48c7-bf74-b04dba05397f.yes": [
"146b4f6d-248a-421a-85bd-5c3f86de67aa.state"
],
"90a2763a-32c3-4aa9-9c88-d803a4e4329b.value": [
"8aa0d95f-300b-4b73-9529-bd708512fd8f.value"
],
"302909ac-3c34-4690-a69d-dcee2bba6905.value": [
"fe99b452-e260-4dc8-a8eb-6d6de1cb8d0d.value"
],
"7eee8c68-8f78-499a-898d-2728429a0e01.value": [
"29f83307-c9b9-48c7-bf74-b04dba05397f.b",
"146b4f6d-248a-421a-85bd-5c3f86de67aa.narrative_direction"
],
"05e031c6-e9e4-414e-bbcd-aa338bae1d3e.value": [
"3b0e09ba-a3eb-488b-b8a5-532bfc14e2e2.value",
"29f83307-c9b9-48c7-bf74-b04dba05397f.a"
],
"146b4f6d-248a-421a-85bd-5c3f86de67aa.message": [
"fe3b68bd-6853-439d-882b-770db12b6ccd.message"
],
"fe3b68bd-6853-439d-882b-770db12b6ccd.message": [
"440d5bef-4023-4897-a1a1-149c5af3dbd3.state_b"
],
"1a89e3bb-bc71-46b1-8c3a-1072c07f820d.value": [
"b0e1848b-f6f6-42fa-97c8-f0e8b87b8b4c.state"
],
"53da2fa3-4375-4d04-88d6-0f54b0a0d9ef.value": [
"fe95c78d-2a24-4c84-8509-a6024443f2a3.state"
],
"7909b9ac-e61e-4b4b-844f-782ec9de05fd.value": [
"dd7a7e8d-445e-4ba4-8395-2433dc479701.no",
"146b4f6d-248a-421a-85bd-5c3f86de67aa.character"
],
"307ef2f9-2ddc-4dbb-a916-f3eefc0239db.value": [
"0cf22c95-ef4b-4199-b5ef-d364acb36050.value",
"56b7196a-1f22-4882-b8ae-f987936ff056.character"
],
"56b7196a-1f22-4882-b8ae-f987936ff056.character": [
"db3dbe65-087d-45f3-841e-28bc2928a4ff.item0"
],
"56b7196a-1f22-4882-b8ae-f987936ff056.description": [
"ab198058-35a6-4796-b713-4f3678561cb5.string"
],
"ab198058-35a6-4796-b713-4f3678561cb5.result": [
"db3dbe65-087d-45f3-841e-28bc2928a4ff.item1"
],
"db3dbe65-087d-45f3-841e-28bc2928a4ff.result": [
"cd3043d0-a852-4a1f-b22c-2defc600a50a.value"
],
"0edfb297-c55b-48eb-b261-2e3fac66430b.value": [
"b1b25e45-5dac-4b14-9494-6c0fe640926b.value"
],
"b1b25e45-5dac-4b14-9494-6c0fe640926b.value": [
"bc919dfb-39c9-4eab-a452-fdb49f66e4c8.value"
],
"55177ca7-4999-466e-8544-82da9a8af7da.state": [
"60b047db-3570-42f8-9c5a-36dfc1f4424f.value"
],
"55177ca7-4999-466e-8544-82da9a8af7da.state_b": [
"cb1f6271-309c-4d44-ba3a-052353626752.value"
],
"55177ca7-4999-466e-8544-82da9a8af7da.state_c": [
"555836b5-fc4b-4d30-a408-dfe3ed6dacb4.value"
],
"bc919dfb-39c9-4eab-a452-fdb49f66e4c8.value": [
"e4851859-59f4-4004-8e5c-4cdc4fb3064d.state",
"b456bbbb-47b2-4a51-b8d9-210f919337a4.item0"
],
"8aa0d95f-300b-4b73-9529-bd708512fd8f.value": [
"55177ca7-4999-466e-8544-82da9a8af7da.state_b",
"b456bbbb-47b2-4a51-b8d9-210f919337a4.item1"
],
"fe99b452-e260-4dc8-a8eb-6d6de1cb8d0d.value": [
"55177ca7-4999-466e-8544-82da9a8af7da.state_c",
"b456bbbb-47b2-4a51-b8d9-210f919337a4.item2"
],
"b456bbbb-47b2-4a51-b8d9-210f919337a4.result": [
"e4851859-59f4-4004-8e5c-4cdc4fb3064d.description"
],
"c049bcad-7006-47f5-bc10-1aa191571bd8.value": [
"fe95c78d-2a24-4c84-8509-a6024443f2a3.context"
],
"e4851859-59f4-4004-8e5c-4cdc4fb3064d.accepted": [
"55177ca7-4999-466e-8544-82da9a8af7da.state"
]
},
"groups": [
{
"title": "Group",
"x": -21,
"y": -100,
"width": 1152,
"height": 322,
"color": "#3f789e",
"font_size": 24,
"inherited": false
},
{
"title": "Group",
"x": -21,
"y": 225,
"width": 1740,
"height": 817,
"color": "#3f789e",
"font_size": 24,
"inherited": false
},
{
"title": "Validation",
"x": -20,
"y": -1087,
"width": 2395,
"height": 983,
"color": "#b58b2a",
"font_size": 24,
"inherited": false
},
{
"title": "Group",
"x": -21,
"y": 1045,
"width": 1438,
"height": 480,
"color": "#8A8",
"font_size": 24,
"inherited": false
}
],
"comments": [],
"extends": null,
"base_type": "core/Graph",
"inputs": [],
"outputs": [],
"module_properties": {},
"style": {
"title_color": "#572e44",
"node_color": "#392c34",
"icon": "F1719",
"auto_title": null,
"counterpart": null
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,562 @@
{
"title": "Instruct Gamestate Updates",
"id": "135fe6aa-33cf-4ef4-9685-5f5a44fc8f7f",
"properties": {},
"x": 0,
"y": 0,
"width": 200,
"height": 100,
"collapsed": false,
"inherited": false,
"registry": "agernts/director/chat/instructGamestateUpdates",
"nodes": {
"0404af9c-3a1e-4535-b8bc-5e8257f95d20": {
"title": "true",
"id": "0404af9c-3a1e-4535-b8bc-5e8257f95d20",
"properties": {
"value": true
},
"x": 485,
"y": 95,
"width": 210,
"height": 58,
"collapsed": true,
"inherited": false,
"registry": "core/MakeBool",
"base_type": "core/Node"
},
"9eba0f83-4226-4f88-b08e-e9c786b3083b": {
"title": "summarizer",
"id": "9eba0f83-4226-4f88-b08e-e9c786b3083b",
"properties": {
"agent_name": "summarizer"
},
"x": 371,
"y": 182,
"width": 210,
"height": 58,
"collapsed": true,
"inherited": false,
"registry": "agents/GetAgent",
"base_type": "core/Node"
},
"fa4a84ad-a696-4ede-9471-fbef8c1c98ee": {
"title": "GET local.instructions",
"id": "fa4a84ad-a696-4ede-9471-fbef8c1c98ee",
"properties": {
"name": "instructions",
"scope": "local"
},
"x": 21,
"y": 272,
"width": 210,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "state/GetState",
"base_type": "core/Node"
},
"0818b1cc-4ad8-46eb-b736-52816aee2582": {
"title": "Build Prompt",
"id": "0818b1cc-4ad8-46eb-b736-52816aee2582",
"properties": {
"template_file": "base",
"scope": "common",
"instructions": "",
"reserved_tokens": 312,
"limit_max_tokens": 0,
"include_scene_intent": false,
"include_extra_context": false,
"include_memory_context": false,
"include_scene_context": false,
"include_character_context": false,
"include_gamestate_context": true,
"memory_prompt": "",
"prefill_prompt": "PLAN:",
"return_prefill_prompt": false,
"dedupe_enabled": true,
"response_length": 0,
"technical": false
},
"x": 681,
"y": 232,
"width": 304,
"height": 542,
"collapsed": false,
"inherited": false,
"registry": "prompt/BuildPrompt",
"base_type": "core/Node"
},
"691fad16-5ef2-414c-b60f-f67e80c52314": {
"title": "Input Socket",
"id": "691fad16-5ef2-414c-b60f-f67e80c52314",
"properties": {
"input_type": "any",
"input_name": "state",
"input_optional": false,
"input_group": "",
"num": 0
},
"x": 23,
"y": -418,
"width": 210,
"height": 154,
"collapsed": false,
"inherited": false,
"registry": "core/Input",
"base_type": "core/Node"
},
"2768828e-e8e2-4fe8-9899-75066cf7850b": {
"title": "OUT state",
"id": "2768828e-e8e2-4fe8-9899-75066cf7850b",
"properties": {
"output_type": "any",
"output_name": "state",
"num": 0
},
"x": 334,
"y": -416,
"width": 210,
"height": 106,
"collapsed": false,
"inherited": false,
"registry": "core/Output",
"base_type": "core/Node"
},
"25b43bed-e4bf-45c0-87c7-72c5785c1d62": {
"title": "Validate Value Is Set",
"id": "25b43bed-e4bf-45c0-87c7-72c5785c1d62",
"properties": {
"error_message": "`instructions` is a required argument.",
"blank_string_is_unset": true
},
"x": 324,
"y": -146,
"width": 210,
"height": 102,
"collapsed": false,
"inherited": false,
"registry": "validation/ValidateValueIsSet",
"base_type": "core/Node"
},
"76cdeb2c-20c0-413b-a6d3-642ba59ab8b3": {
"title": "SET local.instructions",
"id": "76cdeb2c-20c0-413b-a6d3-642ba59ab8b3",
"properties": {
"name": "instructions",
"scope": "local"
},
"x": 594,
"y": -146,
"width": 210,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "state/SetState",
"base_type": "core/Node"
},
"fa56ec44-2788-4fd4-8ad2-5f9512ddf4b0": {
"title": "OUT instructions",
"id": "fa56ec44-2788-4fd4-8ad2-5f9512ddf4b0",
"properties": {
"output_type": "str",
"output_name": "instructions",
"num": 1
},
"x": 1154,
"y": -126,
"width": 210,
"height": 106,
"collapsed": false,
"inherited": false,
"registry": "core/Output",
"base_type": "core/Node"
},
"97025c52-ac1d-41e5-8ec6-8ea1a7fe635f": {
"title": "Stage 0",
"id": "97025c52-ac1d-41e5-8ec6-8ea1a7fe635f",
"properties": {
"stage": 0
},
"x": 874,
"y": -126,
"width": 210,
"height": 118,
"collapsed": false,
"inherited": false,
"registry": "core/Stage",
"base_type": "core/Node"
},
"8d824394-df20-448d-a2d5-3be176b971ec": {
"title": "data objects",
"id": "8d824394-df20-448d-a2d5-3be176b971ec",
"properties": {},
"x": 1400,
"y": 150,
"width": 140,
"height": 26,
"collapsed": true,
"inherited": false,
"registry": "core/Watch",
"base_type": "core/Node"
},
"75a6f3c1-21a5-47cc-ac25-1627b5a2d4ac": {
"title": "Instructions",
"id": "75a6f3c1-21a5-47cc-ac25-1627b5a2d4ac",
"properties": {
"template": "Use codeblocks containing data structures to propose updates to the existing gamestate structure to fulfill the following task.\n\nIf you use more than one codeblock they will be applied to the data sequentially one after another.\n\nYour codeblock(s) will be passed to a python dict update function call.\n\nTASK: {instructions}\n\nBegin by planning your actions, then provide the necessary code block(s)."
},
"x": 281,
"y": 272,
"width": 210,
"height": 133,
"collapsed": false,
"inherited": false,
"registry": "data/string/AdvancedFormat",
"dynamic_inputs": [
{
"name": "item0",
"type": "*"
}
],
"base_type": "core/DynamicSocketNodeBase"
},
"96be54b5-25d5-445b-bec3-bc3e82c0bf10": {
"title": "Generate Response",
"id": "96be54b5-25d5-445b-bec3-bc3e82c0bf10",
"properties": {
"data_output": true,
"data_multiple": true,
"response_length": 2048,
"action_type": "analyze",
"attempts": 1
},
"x": 1091,
"y": 232,
"width": 262,
"height": 234,
"collapsed": false,
"inherited": false,
"registry": "prompt/GenerateResponse",
"base_type": "core/Node"
},
"a6420009-f16e-4e70-93d5-040e54b25b80": {
"title": "Stage 1",
"id": "a6420009-f16e-4e70-93d5-040e54b25b80",
"properties": {
"stage": 1
},
"x": 1680,
"y": 270,
"width": 210,
"height": 118,
"collapsed": false,
"inherited": false,
"registry": "core/Stage",
"base_type": "core/Node"
},
"fddd74c9-06ef-4fcb-a54d-46758b534f9f": {
"title": "SET local.updates",
"id": "fddd74c9-06ef-4fcb-a54d-46758b534f9f",
"properties": {
"name": "updates",
"scope": "local"
},
"x": 1420,
"y": 270,
"width": 210,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "state/SetState",
"base_type": "core/Node"
},
"0c800d62-1ec6-4e96-9270-dc5ebdb7458a": {
"title": "GET local.updates",
"id": "0c800d62-1ec6-4e96-9270-dc5ebdb7458a",
"properties": {
"name": "updates",
"scope": "local"
},
"x": 1420,
"y": -131,
"width": 210,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "state/GetState",
"base_type": "core/Node"
},
"3f8cb37f-6577-4d25-8cfe-a1b3ee22009c": {
"title": "OUT instructions",
"id": "3f8cb37f-6577-4d25-8cfe-a1b3ee22009c",
"properties": {
"output_type": "dict",
"output_name": "updates",
"num": 2
},
"x": 1711,
"y": -116,
"width": 210,
"height": 106,
"collapsed": false,
"inherited": false,
"registry": "core/Output",
"base_type": "core/Node"
},
"67f3c431-2c42-4918-b32d-e7f988cb00cb": {
"title": "GET local.updates",
"id": "67f3c431-2c42-4918-b32d-e7f988cb00cb",
"properties": {
"name": "updates",
"scope": "local"
},
"x": 20,
"y": 884,
"width": 210,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "state/GetState",
"base_type": "core/Node"
},
"1a8900a1-7cbd-4c6a-8627-c95268f4dc63": {
"title": "Stage 2",
"id": "1a8900a1-7cbd-4c6a-8627-c95268f4dc63",
"properties": {
"stage": 2
},
"x": 1360,
"y": 970,
"width": 210,
"height": 118,
"collapsed": true,
"inherited": false,
"registry": "core/Stage",
"base_type": "core/Node"
},
"5f0fba74-6246-46d6-95aa-093b719a9ef6": {
"title": "Dict Update",
"id": "5f0fba74-6246-46d6-95aa-093b719a9ef6",
"properties": {
"create_copy": false
},
"x": 990,
"y": 940,
"width": 210,
"height": 98,
"collapsed": false,
"inherited": false,
"registry": "data/DictUpdate",
"base_type": "core/Node"
},
"7d0d79b9-93f3-49c9-9e34-3b941686e029": {
"title": "Game State",
"id": "7d0d79b9-93f3-49c9-9e34-3b941686e029",
"properties": {},
"x": 800,
"y": 990,
"width": 140,
"height": 26,
"collapsed": true,
"inherited": false,
"registry": "state/Gamestate",
"base_type": "core/Node"
},
"309dbbd0-4da8-46ff-a72f-c205295d7ecd": {
"title": "Director Action Confirm",
"id": "309dbbd0-4da8-46ff-a72f-c205295d7ecd",
"properties": {
"name": "update_gamestate",
"description": "",
"raise_on_reject": true
},
"x": 520,
"y": 960,
"width": 237,
"height": 146,
"collapsed": false,
"inherited": false,
"registry": "agents/director/chat/ActionConfirm",
"base_type": "core/Node"
},
"43a56733-1e07-49d7-ad80-fa97377ea7cc": {
"title": "Advanced Format",
"id": "43a56733-1e07-49d7-ad80-fa97377ea7cc",
"properties": {
"template": "Update game state:\n\n```\n{updates}\n```"
},
"x": 270,
"y": 1020,
"width": 210,
"height": 133,
"collapsed": false,
"inherited": false,
"registry": "data/string/AdvancedFormat",
"dynamic_inputs": [
{
"name": "item0",
"type": "*"
}
],
"base_type": "core/DynamicSocketNodeBase"
},
"91bcf73f-ef94-4e28-a6a1-681b5f9813a7": {
"title": "Input Socket",
"id": "91bcf73f-ef94-4e28-a6a1-681b5f9813a7",
"properties": {
"input_type": "str",
"input_name": "instructions",
"input_optional": false,
"input_group": "",
"num": 1
},
"x": 24,
"y": -176,
"width": 210,
"height": 154,
"collapsed": false,
"inherited": false,
"registry": "core/Input",
"base_type": "core/Node"
},
"6a3b10a7-fa92-413e-b809-b4a3874d0fc5": {
"title": "Module Style",
"id": "6a3b10a7-fa92-413e-b809-b4a3874d0fc5",
"properties": {
"node_color": "#392c34",
"title_color": "#572e44",
"auto_title": null,
"icon": "F1719"
},
"x": 1140,
"y": -440,
"width": 210,
"height": 110,
"collapsed": false,
"inherited": false,
"registry": "util/ModuleStyle",
"base_type": "core/Node"
}
},
"edges": {
"0404af9c-3a1e-4535-b8bc-5e8257f95d20.value": [
"0818b1cc-4ad8-46eb-b736-52816aee2582.state"
],
"9eba0f83-4226-4f88-b08e-e9c786b3083b.agent": [
"0818b1cc-4ad8-46eb-b736-52816aee2582.agent"
],
"fa4a84ad-a696-4ede-9471-fbef8c1c98ee.value": [
"75a6f3c1-21a5-47cc-ac25-1627b5a2d4ac.item0"
],
"0818b1cc-4ad8-46eb-b736-52816aee2582.state": [
"96be54b5-25d5-445b-bec3-bc3e82c0bf10.state"
],
"0818b1cc-4ad8-46eb-b736-52816aee2582.agent": [
"96be54b5-25d5-445b-bec3-bc3e82c0bf10.agent"
],
"0818b1cc-4ad8-46eb-b736-52816aee2582.prompt": [
"96be54b5-25d5-445b-bec3-bc3e82c0bf10.prompt"
],
"691fad16-5ef2-414c-b60f-f67e80c52314.value": [
"2768828e-e8e2-4fe8-9899-75066cf7850b.value"
],
"25b43bed-e4bf-45c0-87c7-72c5785c1d62.value": [
"76cdeb2c-20c0-413b-a6d3-642ba59ab8b3.value"
],
"76cdeb2c-20c0-413b-a6d3-642ba59ab8b3.value": [
"97025c52-ac1d-41e5-8ec6-8ea1a7fe635f.state"
],
"97025c52-ac1d-41e5-8ec6-8ea1a7fe635f.state": [
"fa56ec44-2788-4fd4-8ad2-5f9512ddf4b0.value"
],
"75a6f3c1-21a5-47cc-ac25-1627b5a2d4ac.result": [
"0818b1cc-4ad8-46eb-b736-52816aee2582.instructions"
],
"96be54b5-25d5-445b-bec3-bc3e82c0bf10.data_obj": [
"8d824394-df20-448d-a2d5-3be176b971ec.value",
"fddd74c9-06ef-4fcb-a54d-46758b534f9f.value"
],
"fddd74c9-06ef-4fcb-a54d-46758b534f9f.value": [
"a6420009-f16e-4e70-93d5-040e54b25b80.state"
],
"0c800d62-1ec6-4e96-9270-dc5ebdb7458a.value": [
"3f8cb37f-6577-4d25-8cfe-a1b3ee22009c.value"
],
"67f3c431-2c42-4918-b32d-e7f988cb00cb.value": [
"309dbbd0-4da8-46ff-a72f-c205295d7ecd.state",
"43a56733-1e07-49d7-ad80-fa97377ea7cc.item0"
],
"5f0fba74-6246-46d6-95aa-093b719a9ef6.dict": [
"1a8900a1-7cbd-4c6a-8627-c95268f4dc63.state"
],
"7d0d79b9-93f3-49c9-9e34-3b941686e029.variables": [
"5f0fba74-6246-46d6-95aa-093b719a9ef6.dict"
],
"309dbbd0-4da8-46ff-a72f-c205295d7ecd.accepted": [
"5f0fba74-6246-46d6-95aa-093b719a9ef6.state",
"5f0fba74-6246-46d6-95aa-093b719a9ef6.dicts"
],
"43a56733-1e07-49d7-ad80-fa97377ea7cc.result": [
"309dbbd0-4da8-46ff-a72f-c205295d7ecd.description"
],
"91bcf73f-ef94-4e28-a6a1-681b5f9813a7.value": [
"25b43bed-e4bf-45c0-87c7-72c5785c1d62.value"
]
},
"groups": [
{
"title": "Validation",
"x": -2,
"y": -498,
"width": 1391,
"height": 515,
"color": "#b58b2a",
"font_size": 24,
"inherited": false
},
{
"title": "Process",
"x": -4,
"y": 20,
"width": 1982,
"height": 780,
"color": "#3f789e",
"font_size": 24,
"inherited": false
},
{
"title": "Process",
"x": -5,
"y": 804,
"width": 1600,
"height": 374,
"color": "#3f789e",
"font_size": 24,
"inherited": false
},
{
"title": "Output",
"x": 1395,
"y": -211,
"width": 551,
"height": 227,
"color": "#8A8",
"font_size": 24,
"inherited": false
}
],
"comments": [],
"extends": null,
"base_type": "core/Graph",
"inputs": [],
"outputs": [],
"module_properties": {},
"style": {
"title_color": "#572e44",
"node_color": "#392c34",
"icon": "F1719",
"auto_title": null,
"counterpart": null
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,837 @@
{
"title": "Instruct Narrator",
"id": "dfd90b27-7aee-45c4-adc4-965addc89178",
"properties": {},
"x": 0,
"y": 0,
"width": 200,
"height": 100,
"collapsed": false,
"inherited": false,
"registry": "agents/director/chat/instructNarrator",
"nodes": {
"524f267d-3fa7-46d3-ba78-f65ff96abad2": {
"title": "Validate Value Is Set",
"id": "524f267d-3fa7-46d3-ba78-f65ff96abad2",
"properties": {
"error_message": "instructions required",
"blank_string_is_unset": true
},
"x": 288,
"y": 61,
"width": 210,
"height": 102,
"collapsed": false,
"inherited": false,
"registry": "validation/ValidateValueIsSet",
"base_type": "core/Node"
},
"fe6cb7d0-a665-44cd-994d-1371893ea7d6": {
"title": "Coallesce",
"id": "fe6cb7d0-a665-44cd-994d-1371893ea7d6",
"properties": {},
"x": 1346,
"y": 1414,
"width": 140,
"height": 86,
"collapsed": false,
"inherited": false,
"registry": "core/Coallesce",
"base_type": "core/Node"
},
"6aa18f2c-0f82-41e2-9c56-32146d381217": {
"title": "Coallesce",
"id": "6aa18f2c-0f82-41e2-9c56-32146d381217",
"properties": {},
"x": 1356,
"y": 1724,
"width": 140,
"height": 86,
"collapsed": false,
"inherited": false,
"registry": "core/Coallesce",
"base_type": "core/Node"
},
"94e45254-61d3-4f3f-bd50-c8e96b800d77": {
"title": "SET local.instructions",
"id": "94e45254-61d3-4f3f-bd50-c8e96b800d77",
"properties": {
"name": "instructions",
"scope": "local"
},
"x": 558,
"y": 51,
"width": 210,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "state/SetState",
"base_type": "core/Node"
},
"89dd2b38-581b-434b-8102-fc869ba30fd0": {
"title": "OUT instructions",
"id": "89dd2b38-581b-434b-8102-fc869ba30fd0",
"properties": {
"output_type": "str",
"output_name": "instructions",
"num": 1
},
"x": 1628,
"y": 80,
"width": 210,
"height": 106,
"collapsed": false,
"inherited": false,
"registry": "core/Output",
"base_type": "core/Node"
},
"3e8d05d9-a4d0-42ce-86de-53dc1e58628c": {
"title": "Validate Value Contained",
"id": "3e8d05d9-a4d0-42ce-86de-53dc1e58628c",
"properties": {
"error_message": "`{value}` is not valid for narration_type. Must be one of \"reveal\", \"describe\" or \"progress\"."
},
"x": 298,
"y": 360,
"width": 210,
"height": 98,
"collapsed": false,
"inherited": false,
"registry": "validation/ValidateValueContained",
"base_type": "core/Node"
},
"e6fed6f1-cde3-4395-9f2d-0fc18d888bfc": {
"title": "SET local.narration_type",
"id": "e6fed6f1-cde3-4395-9f2d-0fc18d888bfc",
"properties": {
"name": "narration_type",
"scope": "local"
},
"x": 568,
"y": 340,
"width": 210,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "state/SetState",
"base_type": "core/Node"
},
"a7995fc9-20eb-411c-8f91-f7619898534b": {
"title": "Stage -1",
"id": "a7995fc9-20eb-411c-8f91-f7619898534b",
"properties": {
"stage": -1
},
"x": 1058,
"y": 250,
"width": 210,
"height": 118,
"collapsed": false,
"inherited": false,
"registry": "core/Stage",
"base_type": "core/Node"
},
"7732ac95-5103-4bc7-8936-57e363cb660a": {
"title": "String Check",
"id": "7732ac95-5103-4bc7-8936-57e363cb660a",
"properties": {
"substring": "describe_character",
"mode": "exact",
"case_sensitive": true
},
"x": 284,
"y": 734,
"width": 248,
"height": 126,
"collapsed": true,
"inherited": false,
"registry": "data/string/StringCheck",
"base_type": "core/Node"
},
"febb377e-be31-49d9-b9c3-bc9d2ea2fc23": {
"title": "RSwitch Advanced",
"id": "febb377e-be31-49d9-b9c3-bc9d2ea2fc23",
"properties": {},
"x": 474,
"y": 794,
"width": 175,
"height": 66,
"collapsed": false,
"inherited": false,
"registry": "core/RSwitchAdvanced",
"base_type": "core/Node"
},
"6acad0c5-0232-46a7-8f01-48ff2713c73f": {
"title": "Validate Value Is Set",
"id": "6acad0c5-0232-46a7-8f01-48ff2713c73f",
"properties": {
"error_message": "`character_name` is required when `narration_type` is \"describe_character\".",
"blank_string_is_unset": true
},
"x": 694,
"y": 784,
"width": 210,
"height": 102,
"collapsed": false,
"inherited": false,
"registry": "validation/ValidateValueIsSet",
"base_type": "core/Node"
},
"ad5ade4b-dad2-4dcb-8859-c2173d6ce18a": {
"title": "SET local.character",
"id": "ad5ade4b-dad2-4dcb-8859-c2173d6ce18a",
"properties": {
"name": "character",
"scope": "local"
},
"x": 984,
"y": 784,
"width": 210,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "state/SetState",
"base_type": "core/Node"
},
"0e1a4c7e-1873-4e8a-aa11-4402689f0b87": {
"title": "OUT character",
"id": "0e1a4c7e-1873-4e8a-aa11-4402689f0b87",
"properties": {
"output_type": "character",
"output_name": "character",
"num": 3
},
"x": 1654,
"y": 784,
"width": 210,
"height": 106,
"collapsed": false,
"inherited": false,
"registry": "core/Output",
"base_type": "core/Node"
},
"0850235a-4a95-48c5-8ae2-8289205897bf": {
"title": "OUT narration_type",
"id": "0850235a-4a95-48c5-8ae2-8289205897bf",
"properties": {
"output_type": "str",
"output_name": "narration_type",
"num": 2
},
"x": 1620,
"y": 340,
"width": 210,
"height": 106,
"collapsed": false,
"inherited": false,
"registry": "core/Output",
"base_type": "core/Node"
},
"09416ce3-ed48-4ab8-bcc5-ae85752900ea": {
"title": "OUT state",
"id": "09416ce3-ed48-4ab8-bcc5-ae85752900ea",
"properties": {
"output_type": "any",
"output_name": "state",
"num": 0
},
"x": 280,
"y": -170,
"width": 210,
"height": 106,
"collapsed": false,
"inherited": false,
"registry": "core/Output",
"base_type": "core/Node"
},
"b62840fa-7a4b-48b7-bc6f-16171d156d76": {
"title": "Module Style",
"id": "b62840fa-7a4b-48b7-bc6f-16171d156d76",
"properties": {
"node_color": "#392c34",
"title_color": "#572e44",
"auto_title": null,
"icon": "F1719"
},
"x": 1630,
"y": -150,
"width": 210,
"height": 110,
"collapsed": false,
"inherited": false,
"registry": "util/ModuleStyle",
"base_type": "core/Node"
},
"6549fbbd-e84c-47ec-b4e3-5bc713f3d4f5": {
"title": "Stage 0",
"id": "6549fbbd-e84c-47ec-b4e3-5bc713f3d4f5",
"properties": {
"stage": 0
},
"x": 1320,
"y": 790,
"width": 210,
"height": 118,
"collapsed": false,
"inherited": false,
"registry": "core/Stage",
"base_type": "core/Node"
},
"478d0589-e430-4d00-ac53-49c784cdecce": {
"title": "GET local.narration_type",
"id": "478d0589-e430-4d00-ac53-49c784cdecce",
"properties": {
"name": "narration_type",
"scope": "local"
},
"x": -3,
"y": 1530,
"width": 210,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "state/GetState",
"base_type": "core/Node"
},
"33724449-7640-47da-9351-0787d74f9d79": {
"title": "Case",
"id": "33724449-7640-47da-9351-0787d74f9d79",
"properties": {
"attribute_name": "",
"case_a": "progress",
"case_b": "reveal",
"case_c": "describe_character",
"case_d": "describe_scene"
},
"x": 337,
"y": 1650,
"width": 210,
"height": 234,
"collapsed": false,
"inherited": false,
"registry": "core/Case",
"base_type": "core/Node"
},
"22048751-dfdb-4e01-af81-69a32aff4bf6": {
"title": "GET local.character",
"id": "22048751-dfdb-4e01-af81-69a32aff4bf6",
"properties": {
"name": "character",
"scope": "local"
},
"x": 787,
"y": 1720,
"width": 210,
"height": 122,
"collapsed": true,
"inherited": false,
"registry": "state/GetState",
"base_type": "core/Node"
},
"5bd51ff2-661f-479d-a8ec-92cfa662e2aa": {
"title": "Case",
"id": "5bd51ff2-661f-479d-a8ec-92cfa662e2aa",
"properties": {
"attribute_name": "",
"case_a": "describe_environment",
"case_b": "",
"case_c": "",
"case_d": ""
},
"x": 686,
"y": 1894,
"width": 210,
"height": 234,
"collapsed": false,
"inherited": false,
"registry": "core/Case",
"base_type": "core/Node"
},
"40726545-c86a-4d85-8610-2c49d610347a": {
"title": "GET local.instructions",
"id": "40726545-c86a-4d85-8610-2c49d610347a",
"properties": {
"name": "instructions",
"scope": "local"
},
"x": -10,
"y": 1125,
"width": 210,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "state/GetState",
"base_type": "core/Node"
},
"7c0fc92d-568e-497e-8cb3-1fd94e0d11d2": {
"title": "OUT summary",
"id": "7c0fc92d-568e-497e-8cb3-1fd94e0d11d2",
"properties": {
"output_type": "str",
"output_name": "summary",
"num": 3
},
"x": 2927,
"y": 1450,
"width": 210,
"height": 106,
"collapsed": false,
"inherited": false,
"registry": "core/Output",
"base_type": "core/Node"
},
"7f3a6455-1ff4-4e41-92df-b42fb87b3fbb": {
"title": "Push History",
"id": "7f3a6455-1ff4-4e41-92df-b42fb87b3fbb",
"properties": {
"emit_message": true
},
"x": 2260,
"y": 1570,
"width": 210,
"height": 58,
"collapsed": false,
"inherited": false,
"registry": "scene/history/Push",
"base_type": "core/Node"
},
"4f6659ce-6a14-4553-bb0f-cfb677e185bf": {
"title": "Stage 1",
"id": "4f6659ce-6a14-4553-bb0f-cfb677e185bf",
"properties": {
"stage": 1
},
"x": 2930,
"y": 1700,
"width": 210,
"height": 118,
"collapsed": false,
"inherited": false,
"registry": "core/Stage",
"base_type": "core/Node"
},
"abd90939-40b3-4371-817c-d23e51668057": {
"title": "Director Action Confirm",
"id": "abd90939-40b3-4371-817c-d23e51668057",
"properties": {
"name": "instruct_narrator",
"description": "",
"raise_on_reject": true
},
"x": 1967,
"y": 1520,
"width": 237,
"height": 146,
"collapsed": false,
"inherited": false,
"registry": "agents/director/chat/ActionConfirm",
"base_type": "core/Node"
},
"704a9416-3008-4532-943b-a65855c30f00": {
"title": "Coallesce",
"id": "704a9416-3008-4532-943b-a65855c30f00",
"properties": {},
"x": 1536,
"y": 1564,
"width": 140,
"height": 86,
"collapsed": false,
"inherited": false,
"registry": "core/Coallesce",
"base_type": "core/Node"
},
"c69c06e5-59a2-4e86-8bbf-ed27669000c6": {
"title": "Advanced Format",
"id": "c69c06e5-59a2-4e86-8bbf-ed27669000c6",
"properties": {
"template": "### Instructions\n```\n{instructions}\n```\n\n### Narration\n``` scene\n{value}\n```"
},
"x": 1720,
"y": 1510,
"width": 210,
"height": 153,
"collapsed": false,
"inherited": false,
"registry": "data/string/AdvancedFormat",
"dynamic_inputs": [
{
"name": "item0",
"type": "*"
},
{
"name": "item1",
"type": "*"
}
],
"base_type": "core/DynamicSocketNodeBase"
},
"d195cf7d-85be-4d4d-ba8e-f49ea2fce774": {
"title": "Advanced Format",
"id": "d195cf7d-85be-4d4d-ba8e-f49ea2fce774",
"properties": {
"template": "New narration generated and appended to the scene: \n\n```\n{message.message}\n```"
},
"x": 2512,
"y": 1564,
"width": 210,
"height": 133,
"collapsed": false,
"inherited": false,
"registry": "data/string/AdvancedFormat",
"dynamic_inputs": [
{
"name": "item0",
"type": "*"
}
],
"base_type": "core/DynamicSocketNodeBase"
},
"c7d41761-c4d1-4624-9b69-4b79bab43f5e": {
"title": "GET local.narration_type",
"id": "c7d41761-c4d1-4624-9b69-4b79bab43f5e",
"properties": {
"name": "narration_type",
"scope": "local"
},
"x": 0,
"y": 670,
"width": 210,
"height": 122,
"collapsed": false,
"inherited": false,
"registry": "state/GetState",
"base_type": "core/Node"
},
"22549507-7be8-4a3c-a7ef-a0bc81d83912": {
"title": "IN state",
"id": "22549507-7be8-4a3c-a7ef-a0bc81d83912",
"properties": {
"input_type": "any",
"input_name": "state",
"input_optional": false,
"input_group": "",
"num": 0
},
"x": 0,
"y": -170,
"width": 210,
"height": 154,
"collapsed": false,
"inherited": false,
"registry": "core/Input",
"base_type": "core/Node"
},
"f08ff23c-7d37-4ee2-9aed-104d5156fd5c": {
"title": "Generate Progress Narration",
"id": "f08ff23c-7d37-4ee2-9aed-104d5156fd5c",
"properties": {
"response_length": 2048
},
"x": 995,
"y": 1292,
"width": 245,
"height": 98,
"collapsed": false,
"inherited": false,
"registry": "agents/narrator/GenerateProgress",
"base_type": "core/Node"
},
"2f7f3961-f272-43bb-a9b3-a7eca3397fca": {
"title": "Generate Progress Narration",
"id": "2f7f3961-f272-43bb-a9b3-a7eca3397fca",
"properties": {
"response_length": 1024
},
"x": 995,
"y": 1452,
"width": 245,
"height": 98,
"collapsed": false,
"inherited": false,
"registry": "agents/narrator/GenerateProgress",
"base_type": "core/Node"
},
"a880fccf-c7b7-4863-9310-0abdb139a9e1": {
"title": "Generate Character Narration",
"id": "a880fccf-c7b7-4863-9310-0abdb139a9e1",
"properties": {
"response_length": 1024
},
"x": 997,
"y": 1600,
"width": 245,
"height": 118,
"collapsed": false,
"inherited": false,
"registry": "agents/narrator/GenerateCharacterNarration",
"base_type": "core/Node"
},
"f50201f1-0125-44cd-a635-18ad440e9f68": {
"title": "Generate Scene Narration",
"id": "f50201f1-0125-44cd-a635-18ad440e9f68",
"properties": {
"response_length": 1024
},
"x": 996,
"y": 1774,
"width": 245,
"height": 98,
"collapsed": false,
"inherited": false,
"registry": "agents/narrator/GenerateSceneNarration",
"base_type": "core/Node"
},
"398b61e1-a41d-47c2-9213-4030ead5ed7e": {
"title": "Generate Environment Narration",
"id": "398b61e1-a41d-47c2-9213-4030ead5ed7e",
"properties": {
"response_length": 1024
},
"x": 1010,
"y": 1940,
"width": 252,
"height": 98,
"collapsed": false,
"inherited": false,
"registry": "agents/narrator/GenerateEnvironmentNarration",
"base_type": "core/Node"
},
"dcee2179-aa06-43a5-8c5d-aa29b2cedd4c": {
"title": "IN character",
"id": "dcee2179-aa06-43a5-8c5d-aa29b2cedd4c",
"properties": {
"input_type": "character",
"input_name": "character",
"input_optional": true,
"input_group": "",
"num": 3
},
"x": 0,
"y": 860,
"width": 210,
"height": 154,
"collapsed": false,
"inherited": false,
"registry": "core/Input",
"base_type": "core/Node"
},
"a9606e1d-525d-467c-8889-cfcc284eb42d": {
"title": "Make List",
"id": "a9606e1d-525d-467c-8889-cfcc284eb42d",
"properties": {
"item_type": "any",
"items": [
"progress",
"reveal",
"describe_character",
"describe_scene",
"describe_environment"
]
},
"x": 20,
"y": 510,
"width": 210,
"height": 102,
"collapsed": true,
"inherited": false,
"registry": "data/MakeList",
"base_type": "core/Node"
},
"94113c62-f468-4e78-8460-d6c0a35f0254": {
"title": "IN narration_type",
"id": "94113c62-f468-4e78-8460-d6c0a35f0254",
"properties": {
"input_type": "str",
"input_name": "narration_type",
"input_optional": false,
"input_group": "",
"num": 2
},
"x": 0,
"y": 280,
"width": 210,
"height": 154,
"collapsed": false,
"inherited": false,
"registry": "core/Input",
"base_type": "core/Node"
},
"fdaa6404-8db2-421a-9fb0-d46361189692": {
"title": "IN instructions",
"id": "fdaa6404-8db2-421a-9fb0-d46361189692",
"properties": {
"input_type": "str",
"input_name": "instructions",
"input_optional": false,
"input_group": "",
"num": 1
},
"x": 0,
"y": 50,
"width": 210,
"height": 154,
"collapsed": false,
"inherited": false,
"registry": "core/Input",
"base_type": "core/Node"
}
},
"edges": {
"524f267d-3fa7-46d3-ba78-f65ff96abad2.value": [
"94e45254-61d3-4f3f-bd50-c8e96b800d77.value"
],
"fe6cb7d0-a665-44cd-994d-1371893ea7d6.value": [
"704a9416-3008-4532-943b-a65855c30f00.a"
],
"6aa18f2c-0f82-41e2-9c56-32146d381217.value": [
"704a9416-3008-4532-943b-a65855c30f00.b"
],
"94e45254-61d3-4f3f-bd50-c8e96b800d77.value": [
"a7995fc9-20eb-411c-8f91-f7619898534b.state"
],
"3e8d05d9-a4d0-42ce-86de-53dc1e58628c.value": [
"e6fed6f1-cde3-4395-9f2d-0fc18d888bfc.value"
],
"e6fed6f1-cde3-4395-9f2d-0fc18d888bfc.value": [
"a7995fc9-20eb-411c-8f91-f7619898534b.state_b"
],
"a7995fc9-20eb-411c-8f91-f7619898534b.state": [
"89dd2b38-581b-434b-8102-fc869ba30fd0.value"
],
"a7995fc9-20eb-411c-8f91-f7619898534b.state_b": [
"0850235a-4a95-48c5-8ae2-8289205897bf.value"
],
"7732ac95-5103-4bc7-8936-57e363cb660a.result": [
"febb377e-be31-49d9-b9c3-bc9d2ea2fc23.check"
],
"febb377e-be31-49d9-b9c3-bc9d2ea2fc23.yes": [
"6acad0c5-0232-46a7-8f01-48ff2713c73f.value"
],
"6acad0c5-0232-46a7-8f01-48ff2713c73f.value": [
"ad5ade4b-dad2-4dcb-8859-c2173d6ce18a.value"
],
"ad5ade4b-dad2-4dcb-8859-c2173d6ce18a.value": [
"6549fbbd-e84c-47ec-b4e3-5bc713f3d4f5.state"
],
"6549fbbd-e84c-47ec-b4e3-5bc713f3d4f5.state": [
"0e1a4c7e-1873-4e8a-aa11-4402689f0b87.value"
],
"478d0589-e430-4d00-ac53-49c784cdecce.value": [
"33724449-7640-47da-9351-0787d74f9d79.value"
],
"33724449-7640-47da-9351-0787d74f9d79.a": [
"f08ff23c-7d37-4ee2-9aed-104d5156fd5c.state"
],
"33724449-7640-47da-9351-0787d74f9d79.b": [
"2f7f3961-f272-43bb-a9b3-a7eca3397fca.state"
],
"33724449-7640-47da-9351-0787d74f9d79.c": [
"a880fccf-c7b7-4863-9310-0abdb139a9e1.state"
],
"33724449-7640-47da-9351-0787d74f9d79.d": [
"f50201f1-0125-44cd-a635-18ad440e9f68.state"
],
"33724449-7640-47da-9351-0787d74f9d79.none": [
"5bd51ff2-661f-479d-a8ec-92cfa662e2aa.value"
],
"22048751-dfdb-4e01-af81-69a32aff4bf6.value": [
"a880fccf-c7b7-4863-9310-0abdb139a9e1.character"
],
"5bd51ff2-661f-479d-a8ec-92cfa662e2aa.a": [
"398b61e1-a41d-47c2-9213-4030ead5ed7e.state"
],
"40726545-c86a-4d85-8610-2c49d610347a.value": [
"c69c06e5-59a2-4e86-8bbf-ed27669000c6.item0",
"f08ff23c-7d37-4ee2-9aed-104d5156fd5c.narrative_direction",
"2f7f3961-f272-43bb-a9b3-a7eca3397fca.narrative_direction",
"a880fccf-c7b7-4863-9310-0abdb139a9e1.narrative_direction",
"f50201f1-0125-44cd-a635-18ad440e9f68.narrative_direction",
"398b61e1-a41d-47c2-9213-4030ead5ed7e.narrative_direction"
],
"7f3a6455-1ff4-4e41-92df-b42fb87b3fbb.message": [
"d195cf7d-85be-4d4d-ba8e-f49ea2fce774.item0"
],
"abd90939-40b3-4371-817c-d23e51668057.accepted": [
"7f3a6455-1ff4-4e41-92df-b42fb87b3fbb.message"
],
"704a9416-3008-4532-943b-a65855c30f00.value": [
"abd90939-40b3-4371-817c-d23e51668057.state",
"c69c06e5-59a2-4e86-8bbf-ed27669000c6.item1"
],
"c69c06e5-59a2-4e86-8bbf-ed27669000c6.result": [
"abd90939-40b3-4371-817c-d23e51668057.description"
],
"d195cf7d-85be-4d4d-ba8e-f49ea2fce774.result": [
"7c0fc92d-568e-497e-8cb3-1fd94e0d11d2.value",
"4f6659ce-6a14-4553-bb0f-cfb677e185bf.state"
],
"c7d41761-c4d1-4624-9b69-4b79bab43f5e.value": [
"7732ac95-5103-4bc7-8936-57e363cb660a.string"
],
"22549507-7be8-4a3c-a7ef-a0bc81d83912.value": [
"09416ce3-ed48-4ab8-bcc5-ae85752900ea.value"
],
"f08ff23c-7d37-4ee2-9aed-104d5156fd5c.message": [
"fe6cb7d0-a665-44cd-994d-1371893ea7d6.a"
],
"2f7f3961-f272-43bb-a9b3-a7eca3397fca.message": [
"fe6cb7d0-a665-44cd-994d-1371893ea7d6.b"
],
"a880fccf-c7b7-4863-9310-0abdb139a9e1.message": [
"fe6cb7d0-a665-44cd-994d-1371893ea7d6.c"
],
"f50201f1-0125-44cd-a635-18ad440e9f68.message": [
"fe6cb7d0-a665-44cd-994d-1371893ea7d6.d"
],
"398b61e1-a41d-47c2-9213-4030ead5ed7e.message": [
"6aa18f2c-0f82-41e2-9c56-32146d381217.a"
],
"dcee2179-aa06-43a5-8c5d-aa29b2cedd4c.value": [
"febb377e-be31-49d9-b9c3-bc9d2ea2fc23.yes"
],
"a9606e1d-525d-467c-8889-cfcc284eb42d.list": [
"3e8d05d9-a4d0-42ce-86de-53dc1e58628c.list"
],
"94113c62-f468-4e78-8460-d6c0a35f0254.value": [
"3e8d05d9-a4d0-42ce-86de-53dc1e58628c.value"
],
"fdaa6404-8db2-421a-9fb0-d46361189692.value": [
"524f267d-3fa7-46d3-ba78-f65ff96abad2.value"
]
},
"groups": [
{
"title": "Validation",
"x": -31,
"y": -230,
"width": 1905,
"height": 1277,
"color": "#b58b2a",
"font_size": 24,
"inherited": false
},
{
"title": "Process",
"x": -35,
"y": 1050,
"width": 3295,
"height": 1102,
"color": "#3f789e",
"font_size": 24,
"inherited": false
}
],
"comments": [],
"extends": null,
"base_type": "core/Graph",
"inputs": [],
"outputs": [],
"module_properties": {},
"style": {
"title_color": "#572e44",
"node_color": "#392c34",
"icon": "F1719",
"auto_title": null,
"counterpart": null
}
}

Some files were not shown because too many files have changed in this diff Show More