Spaces:
Running
Running
Add scene setup: relationship, name, context
Browse files- static/app.js +33 -2
- static/index.html +26 -1
- static/styles.css +51 -0
static/app.js
CHANGED
|
@@ -106,6 +106,10 @@ const state = {
|
|
| 106 |
timerInterval: null,
|
| 107 |
showTimer: true,
|
| 108 |
tensionMode: false,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 109 |
};
|
| 110 |
|
| 111 |
// DOM Elements
|
|
@@ -125,6 +129,9 @@ function cacheElements() {
|
|
| 125 |
elements.beginBtn = document.getElementById('begin-btn');
|
| 126 |
elements.showTimerCheckbox = document.getElementById('show-timer');
|
| 127 |
elements.tensionModeCheckbox = document.getElementById('tension-mode');
|
|
|
|
|
|
|
|
|
|
| 128 |
|
| 129 |
elements.roundDisplay = document.getElementById('round-display');
|
| 130 |
elements.endSessionBtn = document.getElementById('end-session-btn');
|
|
@@ -212,8 +219,16 @@ function showScreen(screenName) {
|
|
| 212 |
}
|
| 213 |
|
| 214 |
function handleBeginPractice() {
|
|
|
|
| 215 |
state.showTimer = elements.showTimerCheckbox.checked;
|
| 216 |
state.tensionMode = elements.tensionModeCheckbox.checked;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 217 |
state.round = 1;
|
| 218 |
state.messages = [];
|
| 219 |
state.reflections = [];
|
|
@@ -372,6 +387,20 @@ function hideModal() {
|
|
| 372 |
elements.groundingModal.classList.add('hidden');
|
| 373 |
}
|
| 374 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 375 |
// API Calls - now go through backend
|
| 376 |
async function getClaudeResponse(userMessage) {
|
| 377 |
const conversationHistory = state.messages.map(m => ({
|
|
@@ -379,9 +408,11 @@ async function getClaudeResponse(userMessage) {
|
|
| 379 |
content: m.content
|
| 380 |
}));
|
| 381 |
|
|
|
|
|
|
|
| 382 |
const systemPrompt = state.tensionMode
|
| 383 |
-
? CONFIG.systemPromptTension
|
| 384 |
-
: CONFIG.systemPromptStandard
|
| 385 |
|
| 386 |
const response = await fetch('/api/chat', {
|
| 387 |
method: 'POST',
|
|
|
|
| 106 |
timerInterval: null,
|
| 107 |
showTimer: true,
|
| 108 |
tensionMode: false,
|
| 109 |
+
// Scene setup
|
| 110 |
+
relationshipType: 'partner',
|
| 111 |
+
personName: '',
|
| 112 |
+
context: '',
|
| 113 |
};
|
| 114 |
|
| 115 |
// DOM Elements
|
|
|
|
| 129 |
elements.beginBtn = document.getElementById('begin-btn');
|
| 130 |
elements.showTimerCheckbox = document.getElementById('show-timer');
|
| 131 |
elements.tensionModeCheckbox = document.getElementById('tension-mode');
|
| 132 |
+
elements.relationshipType = document.getElementById('relationship-type');
|
| 133 |
+
elements.personName = document.getElementById('person-name');
|
| 134 |
+
elements.contextInput = document.getElementById('context');
|
| 135 |
|
| 136 |
elements.roundDisplay = document.getElementById('round-display');
|
| 137 |
elements.endSessionBtn = document.getElementById('end-session-btn');
|
|
|
|
| 219 |
}
|
| 220 |
|
| 221 |
function handleBeginPractice() {
|
| 222 |
+
// Capture settings
|
| 223 |
state.showTimer = elements.showTimerCheckbox.checked;
|
| 224 |
state.tensionMode = elements.tensionModeCheckbox.checked;
|
| 225 |
+
|
| 226 |
+
// Capture scene setup
|
| 227 |
+
state.relationshipType = elements.relationshipType.value;
|
| 228 |
+
state.personName = elements.personName.value.trim();
|
| 229 |
+
state.context = elements.contextInput.value.trim();
|
| 230 |
+
|
| 231 |
+
// Reset session
|
| 232 |
state.round = 1;
|
| 233 |
state.messages = [];
|
| 234 |
state.reflections = [];
|
|
|
|
| 387 |
elements.groundingModal.classList.add('hidden');
|
| 388 |
}
|
| 389 |
|
| 390 |
+
// Build scene context for system prompt
|
| 391 |
+
function buildSceneContext() {
|
| 392 |
+
const name = state.personName || 'this person';
|
| 393 |
+
const rel = state.relationshipType;
|
| 394 |
+
|
| 395 |
+
let scene = `You are ${name}, the user's ${rel}.`;
|
| 396 |
+
|
| 397 |
+
if (state.context) {
|
| 398 |
+
scene += ` Context: ${state.context}.`;
|
| 399 |
+
}
|
| 400 |
+
|
| 401 |
+
return scene;
|
| 402 |
+
}
|
| 403 |
+
|
| 404 |
// API Calls - now go through backend
|
| 405 |
async function getClaudeResponse(userMessage) {
|
| 406 |
const conversationHistory = state.messages.map(m => ({
|
|
|
|
| 408 |
content: m.content
|
| 409 |
}));
|
| 410 |
|
| 411 |
+
const sceneContext = buildSceneContext();
|
| 412 |
+
|
| 413 |
const systemPrompt = state.tensionMode
|
| 414 |
+
? `${sceneContext}\n\n${CONFIG.systemPromptTension}`
|
| 415 |
+
: `${sceneContext}\n\n${CONFIG.systemPromptStandard}`;
|
| 416 |
|
| 417 |
const response = await fetch('/api/chat', {
|
| 418 |
method: 'POST',
|
static/index.html
CHANGED
|
@@ -28,6 +28,31 @@
|
|
| 28 |
<p><em>Imagine you're texting someone whose response matters to you — a partner, friend, family member, or someone you're getting to know. The AI will respond as that person might.</em></p>
|
| 29 |
</div>
|
| 30 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
<div class="practice-options">
|
| 32 |
<h3>Practice Settings</h3>
|
| 33 |
|
|
@@ -44,7 +69,7 @@
|
|
| 44 |
<input type="checkbox" id="tension-mode">
|
| 45 |
<span class="toggle-text">Enable stretch mode</span>
|
| 46 |
</label>
|
| 47 |
-
<p class="option-description">
|
| 48 |
</div>
|
| 49 |
</div>
|
| 50 |
|
|
|
|
| 28 |
<p><em>Imagine you're texting someone whose response matters to you — a partner, friend, family member, or someone you're getting to know. The AI will respond as that person might.</em></p>
|
| 29 |
</div>
|
| 30 |
|
| 31 |
+
<div class="practice-setup">
|
| 32 |
+
<h3>Set the Scene</h3>
|
| 33 |
+
|
| 34 |
+
<div class="setup-row">
|
| 35 |
+
<label for="relationship-type">Who are you texting?</label>
|
| 36 |
+
<select id="relationship-type">
|
| 37 |
+
<option value="partner">Partner</option>
|
| 38 |
+
<option value="friend">Friend</option>
|
| 39 |
+
<option value="family">Family member</option>
|
| 40 |
+
<option value="new">Someone new</option>
|
| 41 |
+
<option value="ex">Ex</option>
|
| 42 |
+
</select>
|
| 43 |
+
</div>
|
| 44 |
+
|
| 45 |
+
<div class="setup-row">
|
| 46 |
+
<label for="person-name">Their name (optional)</label>
|
| 47 |
+
<input type="text" id="person-name" placeholder="e.g., Sam">
|
| 48 |
+
</div>
|
| 49 |
+
|
| 50 |
+
<div class="setup-row">
|
| 51 |
+
<label for="context">Brief context (optional)</label>
|
| 52 |
+
<input type="text" id="context" placeholder="e.g., We were supposed to meet up today">
|
| 53 |
+
</div>
|
| 54 |
+
</div>
|
| 55 |
+
|
| 56 |
<div class="practice-options">
|
| 57 |
<h3>Practice Settings</h3>
|
| 58 |
|
|
|
|
| 69 |
<input type="checkbox" id="tension-mode">
|
| 70 |
<span class="toggle-text">Enable stretch mode</span>
|
| 71 |
</label>
|
| 72 |
+
<p class="option-description">They'll be distracted, brief, and not fully present — realistic friction to stretch your tolerance.</p>
|
| 73 |
</div>
|
| 74 |
</div>
|
| 75 |
|
static/styles.css
CHANGED
|
@@ -174,6 +174,57 @@ body {
|
|
| 174 |
margin-top: var(--space-xs);
|
| 175 |
}
|
| 176 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 177 |
/* Practice Options */
|
| 178 |
.practice-options {
|
| 179 |
background: var(--cream-dark);
|
|
|
|
| 174 |
margin-top: var(--space-xs);
|
| 175 |
}
|
| 176 |
|
| 177 |
+
/* Practice Setup */
|
| 178 |
+
.practice-setup {
|
| 179 |
+
background: var(--white);
|
| 180 |
+
padding: var(--space-md);
|
| 181 |
+
border-radius: var(--radius-md);
|
| 182 |
+
margin-bottom: var(--space-md);
|
| 183 |
+
box-shadow: 0 1px 4px var(--warm-shadow);
|
| 184 |
+
}
|
| 185 |
+
|
| 186 |
+
.practice-setup h3 {
|
| 187 |
+
font-size: 1rem;
|
| 188 |
+
font-weight: 500;
|
| 189 |
+
color: var(--sage-dark);
|
| 190 |
+
margin-bottom: var(--space-md);
|
| 191 |
+
font-family: var(--font-ui);
|
| 192 |
+
}
|
| 193 |
+
|
| 194 |
+
.setup-row {
|
| 195 |
+
margin-bottom: var(--space-md);
|
| 196 |
+
}
|
| 197 |
+
|
| 198 |
+
.setup-row:last-child {
|
| 199 |
+
margin-bottom: 0;
|
| 200 |
+
}
|
| 201 |
+
|
| 202 |
+
.setup-row label {
|
| 203 |
+
display: block;
|
| 204 |
+
font-family: var(--font-ui);
|
| 205 |
+
font-size: 0.9rem;
|
| 206 |
+
font-weight: 500;
|
| 207 |
+
color: var(--charcoal-light);
|
| 208 |
+
margin-bottom: var(--space-xs);
|
| 209 |
+
}
|
| 210 |
+
|
| 211 |
+
.setup-row select,
|
| 212 |
+
.setup-row input[type="text"] {
|
| 213 |
+
width: 100%;
|
| 214 |
+
padding: var(--space-sm);
|
| 215 |
+
font-family: var(--font-ui);
|
| 216 |
+
font-size: 1rem;
|
| 217 |
+
border: 2px solid var(--soft-border);
|
| 218 |
+
border-radius: var(--radius-sm);
|
| 219 |
+
background: var(--cream);
|
| 220 |
+
}
|
| 221 |
+
|
| 222 |
+
.setup-row select:focus,
|
| 223 |
+
.setup-row input[type="text"]:focus {
|
| 224 |
+
outline: none;
|
| 225 |
+
border-color: var(--sage);
|
| 226 |
+
}
|
| 227 |
+
|
| 228 |
/* Practice Options */
|
| 229 |
.practice-options {
|
| 230 |
background: var(--cream-dark);
|