diff --git a/src/games/storywriter/assets/chapters-editor.module.css b/src/games/storywriter/assets/chapters-editor.module.css
index 73f5a40..0bf6403 100644
--- a/src/games/storywriter/assets/chapters-editor.module.css
+++ b/src/games/storywriter/assets/chapters-editor.module.css
@@ -71,6 +71,7 @@
min-height: 80px;
white-space: pre-wrap;
word-wrap: break-word;
+ resize: vertical;
&:focus {
outline: none;
diff --git a/src/games/storywriter/components/chapters-editor.tsx b/src/games/storywriter/components/chapters-editor.tsx
index 73e7cb3..68a1e78 100644
--- a/src/games/storywriter/components/chapters-editor.tsx
+++ b/src/games/storywriter/components/chapters-editor.tsx
@@ -44,6 +44,7 @@ export const ChaptersEditor = () => {
)}
{body}
{
const { currentStory, dispatch, connection, model } = useAppState();
@@ -174,12 +175,12 @@ export const CharacterEditor = () => {
diff --git a/src/games/storywriter/components/location-editor.tsx b/src/games/storywriter/components/location-editor.tsx
index 65683e7..d11cf4f 100644
--- a/src/games/storywriter/components/location-editor.tsx
+++ b/src/games/storywriter/components/location-editor.tsx
@@ -2,6 +2,7 @@ import { useAppState, type Location, LocationScale } from "../contexts/state";
import { useState } from "preact/hooks";
import styles from '../assets/location-editor.module.css';
import LLM from "../utils/llm";
+import { ContentEditable } from "@common/components/ContentEditable";
const SCALE_OPTIONS = Object.entries(LocationScale)
.filter(([, value]) => typeof value === 'number')
@@ -138,12 +139,12 @@ export const LocationEditor = () => {
diff --git a/src/games/storywriter/utils/tools.ts b/src/games/storywriter/utils/tools.ts
index b4161c3..6b1bce2 100644
--- a/src/games/storywriter/utils/tools.ts
+++ b/src/games/storywriter/utils/tools.ts
@@ -28,7 +28,7 @@ export namespace Tools {
appState.dispatch({
type: 'EDIT_STORY',
id: appState.currentStory.id,
- text: appState.currentStory.text + args.text,
+ text: appState.currentStory.text + '\n' + args.text,
});
appState.dispatch({
type: 'SET_CURRENT_TAB',
@@ -50,7 +50,7 @@ export namespace Tools {
appState.dispatch({
type: 'EDIT_LORE',
id: appState.currentStory.id,
- lore: appState.currentStory.lore + args.text
+ lore: appState.currentStory.lore + '\n' + args.text,
});
appState.dispatch({
type: 'SET_CURRENT_TAB',
@@ -296,7 +296,11 @@ export namespace Tools {
if (!appState.currentStory) {
return 'Error: No story selected';
}
- const lines = appState.currentStory.text.split('\n');
+ const source = args.source === 'lore'
+ ? appState.currentStory.lore
+ : appState.currentStory.text;
+
+ const lines = source.split('\n');
const matches: { line: number; content: string }[] = [];
const pattern = new RegExp(args.pattern, args.case_sensitive ? 'g' : 'gi');
for (let i = 0; i < lines.length; i++) {
@@ -317,11 +321,14 @@ export namespace Tools {
}
return result;
},
- description: 'Search for a pattern in the story text',
+ description: 'Search for a pattern in the story text or lore',
parameters: Type.Object({
pattern: Type.String({ description: 'The regex pattern to search for' }),
case_sensitive: Type.Optional(Type.Boolean({ description: 'If true, search is case-sensitive (default: false)' })),
limit: Type.Optional(Type.Integer({ description: 'Maximum number of matches to return (default: 20)' })),
+ source: Type.Optional(Type.Enum(['lore', 'story'],
+ { description: 'Source to search (story or lore, default: story)' },
+ )),
}),
})
};