clay-server 2.27.0-beta.17 → 2.27.0-beta.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/public/app.js CHANGED
@@ -46,21 +46,23 @@ import { initMateWizard, openMateWizard, closeMateWizard, handleMateCreated } fr
46
46
  import { initCommandPalette, handlePaletteSessionSwitch, setPaletteVersion } from './modules/command-palette.js';
47
47
  import { initLongPress } from './modules/longpress.js';
48
48
  import { initConnection, connect as _connConnect, setStatus as _connSetStatus, scheduleReconnect as _connScheduleReconnect, cancelReconnect as _connCancelReconnect } from './modules/app-connection.js';
49
- import { initMessages, processMessage as _msgProcessMessage } from './modules/app-messages.js';
49
+ import { processMessage as _msgProcessMessage } from './modules/app-messages.js';
50
+ import { setWs as _setWsRef } from './modules/ws-ref.js';
50
51
  import { initHomeHub, showHomeHub as _hubShowHomeHub, hideHomeHub as _hubHideHomeHub, handleHubSchedules as _hubHandleHubSchedules, renderHomeHub as _hubRenderHomeHub, isHomeHubVisible } from './modules/app-home-hub.js';
51
52
  import { initRateLimit, handleRateLimitEvent as _rlHandleRateLimitEvent, updateRateLimitUsage as _rlUpdateRateLimitUsage, addScheduledMessageBubble as _rlAddScheduledMessageBubble, removeScheduledMessageBubble as _rlRemoveScheduledMessageBubble, handleFastModeState as _rlHandleFastModeState, getScheduledMsgEl, resetRateLimitState } from './modules/app-rate-limit.js';
52
53
  import { initCursors, handleRemoteCursorMove as _curHandleRemoteCursorMove, handleRemoteCursorLeave as _curHandleRemoteCursorLeave, handleRemoteSelection as _curHandleRemoteSelection, clearRemoteCursors as _curClearRemoteCursors, initCursorToggle } from './modules/app-cursors.js';
53
54
  import { initFavicon, updateFavicon as _favUpdateFavicon, setSendBtnMode as _favSetSendBtnMode, blinkIO as _favBlinkIO, blinkSessionDot as _favBlinkSessionDot, updateCrossProjectBlink as _favUpdateCrossProjectBlink, startUrgentBlink as _favStartUrgentBlink, stopUrgentBlink as _favStopUrgentBlink, setActivity as _favSetActivity, drawFaviconAnimFrame as _favDrawFaviconAnimFrame } from './modules/app-favicon.js';
54
55
  import { initHeader, closeSessionInfoPopover as _hdrCloseSessionInfoPopover, updateHistorySentinel as _hdrUpdateHistorySentinel, requestMoreHistory as _hdrRequestMoreHistory, prependOlderHistory as _hdrPrependOlderHistory } from './modules/app-header.js';
55
56
  import { initMisc, showImageModal as _miscShowImageModal, closeImageModal as _miscCloseImageModal, showPasteModal as _miscShowPasteModal, closePasteModal as _miscClosePasteModal, showConfirm as _miscShowConfirm, hideConfirm as _miscHideConfirm, showForceChangePinOverlay as _miscShowForceChangePinOverlay, sendExtensionCommand as _miscSendExtensionCommand, handleExtensionResult as _miscHandleExtensionResult } from './modules/app-misc.js';
56
- import { initSkillInstall, requireSkills as _siRequireSkills, requireClayMateInterview as _siRequireClayMateInterview, handleSkillInstallWs as _siHandleSkillInstallWs, getKnownInstalledSkills, setKnownInstalledSkills } from './modules/app-skills-install.js';
57
- import { initDebateUi, showDebateConcludeConfirm as _debShowDebateConcludeConfirm, exitDebateConcludeMode as _debExitDebateConcludeMode, handleDebateConcludeSend as _debHandleDebateConcludeSend, showDebateEndedMode as _debShowDebateEndedMode, exitDebateEndedMode as _debExitDebateEndedMode, showDebateUserFloor as _debShowDebateUserFloor, exitDebateFloorMode as _debExitDebateFloorMode, handleDebateFloorSend as _debHandleDebateFloorSend, renderDebateUserFloorDone as _debRenderDebateUserFloorDone, showDebateSticky as _debShowDebateSticky, showDebateBottomBar as _debShowDebateBottomBar, removeDebateBottomBar as _debRemoveDebateBottomBar, sendDebateStickyComment as _debSendDebateStickyComment, updateDebateRound as _debUpdateDebateRound, getDebateStickyState, setDebateStickyState, getDebateFloorMode, getDebateConcludeMode, getDebateEndedMode } from './modules/app-debate-ui.js';
58
- import { initLoopUi, updateLoopInputVisibility as _loopUpdateLoopInputVisibility, updateLoopButton as _loopUpdateLoopButton, showLoopBanner as _loopShowLoopBanner, updateLoopBanner as _loopUpdateLoopBanner, updateRalphBars as _loopUpdateRalphBars, showRalphCraftingBar as _loopShowRalphCraftingBar, showRalphApprovalBar as _loopShowRalphApprovalBar, updateRalphApprovalStatus as _loopUpdateRalphApprovalStatus, openRalphPreviewModal as _loopOpenRalphPreviewModal, showExecModal as _loopShowExecModal, closeExecModal as _loopCloseExecModal, updateExecModalStatus as _loopUpdateExecModalStatus, getLoopActive, setLoopActive, getLoopAvailable, setLoopAvailable, getLoopIteration, setLoopIteration, getLoopMaxIterations, setLoopMaxIterations, getLoopBannerName, setLoopBannerName, getRalphPhase, setRalphPhase, getRalphCraftingSessionId, setRalphCraftingSessionId, getRalphCraftingSource, setRalphCraftingSource, getRalphFilesReady, setRalphFilesReady, getRalphPreviewContent, setRalphPreviewContent, getExecModalShown, setExecModalShown } from './modules/app-loop-ui.js';
59
- import { initLoopWizard, openRalphWizard as _loopOpenRalphWizard, closeRalphWizard as _loopCloseRalphWizard, getWizardData, setWizardData, getWizardSource as _loopGetWizardSource } from './modules/app-loop-wizard.js';
57
+ import { initSkillInstall, requireSkills as _siRequireSkills, requireClayMateInterview as _siRequireClayMateInterview, handleSkillInstallWs as _siHandleSkillInstallWs } from './modules/app-skills-install.js';
58
+ import { initDebateUi, showDebateConcludeConfirm as _debShowDebateConcludeConfirm, exitDebateConcludeMode as _debExitDebateConcludeMode, handleDebateConcludeSend as _debHandleDebateConcludeSend, showDebateEndedMode as _debShowDebateEndedMode, exitDebateEndedMode as _debExitDebateEndedMode, showDebateUserFloor as _debShowDebateUserFloor, exitDebateFloorMode as _debExitDebateFloorMode, handleDebateFloorSend as _debHandleDebateFloorSend, renderDebateUserFloorDone as _debRenderDebateUserFloorDone, showDebateSticky as _debShowDebateSticky, showDebateBottomBar as _debShowDebateBottomBar, removeDebateBottomBar as _debRemoveDebateBottomBar, sendDebateStickyComment as _debSendDebateStickyComment, updateDebateRound as _debUpdateDebateRound } from './modules/app-debate-ui.js';
59
+ import { initLoopUi, updateLoopInputVisibility as _loopUpdateLoopInputVisibility, updateLoopButton as _loopUpdateLoopButton, showLoopBanner as _loopShowLoopBanner, updateLoopBanner as _loopUpdateLoopBanner, updateRalphBars as _loopUpdateRalphBars, showRalphCraftingBar as _loopShowRalphCraftingBar, showRalphApprovalBar as _loopShowRalphApprovalBar, updateRalphApprovalStatus as _loopUpdateRalphApprovalStatus, openRalphPreviewModal as _loopOpenRalphPreviewModal, showExecModal as _loopShowExecModal, closeExecModal as _loopCloseExecModal, updateExecModalStatus as _loopUpdateExecModalStatus } from './modules/app-loop-ui.js';
60
+ import { initLoopWizard, openRalphWizard as _loopOpenRalphWizard, closeRalphWizard as _loopCloseRalphWizard, getWizardSource as _loopGetWizardSource } from './modules/app-loop-wizard.js';
60
61
  import { initAppNotifications, handleNotificationsState as _notifHandleState, handleNotificationCreated as _notifHandleCreated, handleNotificationDismissed as _notifHandleDismissed, handleNotificationDismissedAll as _notifHandleDismissedAll } from './modules/app-notifications.js';
61
- import { initPanels, updateConfigChip as _panUpdateConfigChip, getModelEffortLevels as _panGetModelEffortLevels, accumulateUsage as _panAccumulateUsage, updateUsagePanel as _panUpdateUsagePanel, resetUsage as _panResetUsage, toggleUsagePanel as _panToggleUsagePanel, formatTokens as _panFormatTokens, updateStatusPanel as _panUpdateStatusPanel, requestProcessStats as _panRequestProcessStats, toggleStatusPanel as _panToggleStatusPanel, accumulateContext as _panAccumulateContext, updateContextPanel as _panUpdateContextPanel, resetContext as _panResetContext, resetContextData as _panResetContextData, minimizeContext as _panMinimizeContext, expandContext as _panExpandContext, toggleContextPanel as _panToggleContextPanel, getContextView as _panGetContextView, renderCtxPopover as _panRenderCtxPopover, hideCtxPopover as _panHideCtxPopover, formatBytes as _panFormatBytes, formatUptime as _panFormatUptime, getModelSupportsEffort as _panGetModelSupportsEffort, getCurrentModel, setCurrentModel, getCurrentModels, setCurrentModels, getCurrentMode, setCurrentMode, getCurrentEffort, setCurrentEffort, getCurrentBetas, setCurrentBetas, getCurrentThinking, setCurrentThinking, getCurrentThinkingBudget, setCurrentThinkingBudget, getSessionUsage, setSessionUsage, getContextData, setContextData, getHeaderContextEl as _panGetHeaderContextEl, setHeaderContextEl as _panSetHeaderContextEl, getRichContextUsage, setRichContextUsage, getCtxPopoverVisible, setContextView as _panSetContextView, applyContextView as _panApplyContextView } from './modules/app-panels.js';
62
+ import { createStore, store } from './modules/store.js';
63
+ import { initPanels, updateConfigChip as _panUpdateConfigChip, getModelEffortLevels as _panGetModelEffortLevels, accumulateUsage as _panAccumulateUsage, updateUsagePanel as _panUpdateUsagePanel, resetUsage as _panResetUsage, toggleUsagePanel as _panToggleUsagePanel, formatTokens as _panFormatTokens, updateStatusPanel as _panUpdateStatusPanel, requestProcessStats as _panRequestProcessStats, toggleStatusPanel as _panToggleStatusPanel, accumulateContext as _panAccumulateContext, updateContextPanel as _panUpdateContextPanel, resetContext as _panResetContext, resetContextData as _panResetContextData, minimizeContext as _panMinimizeContext, expandContext as _panExpandContext, toggleContextPanel as _panToggleContextPanel, getContextView as _panGetContextView, renderCtxPopover as _panRenderCtxPopover, hideCtxPopover as _panHideCtxPopover, formatBytes as _panFormatBytes, formatUptime as _panFormatUptime, getModelSupportsEffort as _panGetModelSupportsEffort, getSessionUsage, setSessionUsage, getContextData, setContextData, setContextView as _panSetContextView, applyContextView as _panApplyContextView } from './modules/app-panels.js';
62
64
  import { initProjects, updateProjectList as _projUpdateProjectList, renderProjectList as _projRenderProjectList, renderTopbarPresence as _projRenderTopbarPresence, switchProject as _projSwitchProject, resetClientState as _projResetClientState, confirmRemoveProject as _projConfirmRemoveProject, handleRemoveProjectCheckResult as _projHandleRemoveProjectCheckResult, handleRemoveProjectResult as _projHandleRemoveProjectResult, openAddProjectModal as _projOpenAddProjectModal, closeAddProjectModal as _projCloseAddProjectModal, handleBrowseDirResult as _projHandleBrowseDirResult, handleAddProjectResult as _projHandleAddProjectResult, handleCloneProgress as _projHandleCloneProgress, showUpdateAvailable as _projShowUpdateAvailable, getCachedProjects, setCachedProjects, getCachedProjectCount, getCachedRemovedProjects, setCachedRemovedProjects } from './modules/app-projects.js';
63
- import { initRendering, addToMessages as _renAddToMessages, scrollToBottom as _renScrollToBottom, forceScrollToBottom as _renForceScrollToBottom, addUserMessage as _renAddUserMessage, getMsgTime as _renGetMsgTime, shouldGroupMessage as _renShouldGroupMessage, ensureAssistantBlock as _renEnsureAssistantBlock, addCopyHandler as _renAddCopyHandler, appendDelta as _renAppendDelta, flushStreamBuffer as _renFlushStreamBuffer, finalizeAssistantBlock as _renFinalizeAssistantBlock, addSystemMessage as _renAddSystemMessage, addConflictMessage as _renAddConflictMessage, addContextOverflowMessage as _renAddContextOverflowMessage, addAuthRequiredMessage as _renAddAuthRequiredMessage, showClaudePreThinking as _renShowClaudePreThinking, showMatePreThinking as _renShowMatePreThinking, removeMatePreThinking as _renRemoveMatePreThinking, showSuggestionChips as _renShowSuggestionChips, hideSuggestionChips as _renHideSuggestionChips, getCurrentMsgEl, setCurrentMsgEl, getCurrentFullText, setCurrentFullText, getTurnCounter, setTurnCounter, getPrependAnchor, setPrependAnchor, getActivityEl, setActivityEl, getMatePreThinkingEl, getCurrentMsgTs, setCurrentMsgTs, getIsUserScrolledUp, setIsUserScrolledUp, getReplayingHistory, setReplayingHistory } from './modules/app-rendering.js';
65
+ import { initRendering, addToMessages as _renAddToMessages, scrollToBottom as _renScrollToBottom, forceScrollToBottom as _renForceScrollToBottom, addUserMessage as _renAddUserMessage, getMsgTime as _renGetMsgTime, shouldGroupMessage as _renShouldGroupMessage, ensureAssistantBlock as _renEnsureAssistantBlock, addCopyHandler as _renAddCopyHandler, appendDelta as _renAppendDelta, flushStreamBuffer as _renFlushStreamBuffer, finalizeAssistantBlock as _renFinalizeAssistantBlock, addSystemMessage as _renAddSystemMessage, addConflictMessage as _renAddConflictMessage, addContextOverflowMessage as _renAddContextOverflowMessage, addAuthRequiredMessage as _renAddAuthRequiredMessage, showClaudePreThinking as _renShowClaudePreThinking, showMatePreThinking as _renShowMatePreThinking, removeMatePreThinking as _renRemoveMatePreThinking, showSuggestionChips as _renShowSuggestionChips, hideSuggestionChips as _renHideSuggestionChips, getTurnCounter, setTurnCounter, getPrependAnchor, setPrependAnchor, getActivityEl, setActivityEl, getIsUserScrolledUp, setIsUserScrolledUp } from './modules/app-rendering.js';
64
66
  import { initDm, openDm as _dmOpenDm, enterDmMode as _dmEnterDmMode, exitDmMode as _dmExitDmMode, handleMateCreatedInApp as _dmHandleMateCreatedInApp, renderAvailableBuiltins as _dmRenderAvailableBuiltins, buildMateInterviewPrompt as _dmBuildMateInterviewPrompt, updateMateIconStatus as _dmUpdateMateIconStatus, connectMateProject as _dmConnectMateProject, disconnectMateProject as _dmDisconnectMateProject, appendDmMessage as _dmAppendDmMessage, showDmTypingIndicator as _dmShowDmTypingIndicator, handleDmSend as _dmHandleDmSend } from './modules/app-dm.js';
65
67
  import { initMention, handleMentionStart, handleMentionStream, handleMentionDone, handleMentionError, handleMentionActivity, renderMentionUser, renderMentionResponse } from './modules/mention.js';
66
68
  import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateResumed, handleDebateTurn, handleDebateActivity, handleDebateStream, handleDebateTurnDone, handleDebateCommentQueued, handleDebateCommentInjected, handleDebateEnded, handleDebateError, renderDebateStarted, renderDebateTurnDone, renderDebateEnded, renderDebateCommentInjected, renderDebateUserResume, openDebateModal, closeDebateModal, handleDebateBriefReady, renderDebateBriefReady, isDebateActive, resetDebateState, exportDebateAsPdf, renderMcpDebateProposal } from './modules/debate.js';
@@ -96,26 +98,15 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
96
98
  var connectOverlay = $("connect-overlay");
97
99
 
98
100
  // --- DM Mode ---
99
- var dmMode = false;
100
- var dmKey = null;
101
- var dmTargetUser = null;
101
+ // dmMode, dmUnread, cachedAllUsers, cachedOnlineIds, cachedDmFavorites,
102
+ // cachedDmConversations, dmRemovedUsers, cachedMatesList, cachedAvailableBuiltins,
103
+ // dmTargetUser, dmKey -> store
102
104
  var dmMessageCache = []; // cached DM messages for quick debate context
103
- var dmUnread = {}; // { otherUserId: count }
104
- var cachedAllUsers = [];
105
- var cachedOnlineIds = [];
106
- var cachedDmFavorites = [];
107
- var cachedDmConversations = [];
108
- var dmRemovedUsers = {}; // { userId: true } - users explicitly removed from favorites
109
- var cachedMatesList = []; // Cached list of mates for user strip
110
- var cachedAvailableBuiltins = []; // Deleted built-in mates available for re-add
111
105
 
112
106
  var CLAUDE_CODE_AVATAR = "/claude-code-avatar.png";
113
107
 
114
108
  // --- Mate project switching ---
115
- var mateProjectSlug = null;
116
- var savedMainSlug = null; // main project slug saved during mate DM
117
- var returningFromMateDm = false; // suppress restore_mate_dm after intentional exit
118
- var pendingMateInterview = null;
109
+ // mateProjectSlug, savedMainSlug, returningFromMateDm, pendingMateInterview -> store
119
110
 
120
111
 
121
112
  // --- Home Hub (delegated to app-home-hub.js) ---
@@ -145,8 +136,8 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
145
136
  var projectHint = $("project-hint");
146
137
  var projectHintDismiss = $("project-hint-dismiss");
147
138
  // cachedProjects, cachedProjectCount, cachedRemovedProjects -> modules/app-projects.js
148
- var currentProjectOwnerId = null;
149
- var currentSlug = slugMatch ? slugMatch[1] : null;
139
+ // currentProjectOwnerId -> store
140
+ var currentSlug = slugMatch ? slugMatch[1] : null; // kept for pre-store init
150
141
 
151
142
  // updateProjectList, renderTopbarPresence, renderProjectList -> modules/app-projects.js
152
143
  function updateProjectList(msg) { _projUpdateProjectList(msg); }
@@ -174,12 +165,12 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
174
165
 
175
166
  document.addEventListener("keydown", function (e) {
176
167
  if (e.key === "Escape") {
177
- if (isHomeHubVisible() && currentSlug) {
168
+ if (isHomeHubVisible() && store.getState().currentSlug) {
178
169
  hideHomeHub();
179
170
  if (document.documentElement.classList.contains("pwa-standalone")) {
180
- history.replaceState(null, "", "/p/" + currentSlug + "/");
171
+ history.replaceState(null, "", "/p/" + store.getState().currentSlug + "/");
181
172
  } else {
182
- history.pushState(null, "", "/p/" + currentSlug + "/");
173
+ history.pushState(null, "", "/p/" + store.getState().currentSlug + "/");
183
174
  }
184
175
  var homeIcon = document.querySelector(".icon-strip-home");
185
176
  if (homeIcon) homeIcon.classList.remove("active");
@@ -219,23 +210,12 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
219
210
 
220
211
  // --- State ---
221
212
  var ws = null;
222
- var connected = false;
223
- var processing = false;
224
- // rateLimitResetsAt, rateLimitResetTimer -> modules/app-rate-limit.js
225
- // isComposing -> modules/input.js
226
- // wasConnected, reconnectTimer, reconnectDelay, disconnectNotifTimer, disconnectNotifShown -> modules/app-connection.js
227
- // activityEl, currentMsgEl, currentFullText, highlightTimer -> modules/app-rendering.js
228
- // tools, currentThinking -> modules/tools.js
229
- var activeSessionId = null;
230
- var sessionDrafts = {};
213
+ // connected, processing, activeSessionId, sessionDrafts -> store
231
214
  // loopActive, loopAvailable, loopIteration, loopMaxIterations, loopBannerName,
232
215
  // ralphPhase, ralphCraftingSessionId, ralphCraftingSource, ralphFilesReady, ralphPreviewContent -> modules/app-loop-ui.js
233
216
  // wizardStep, wizardSource, wizardData, loopModeChoice, promptAuthor, judgeAuthor -> modules/app-loop-wizard.js
234
- var slashCommands = [];
235
- // slashActiveIdx, slashFiltered, pendingImages, pendingPastes -> modules/input.js
236
- // pendingPermissions -> modules/tools.js
237
- var cliSessionId = null;
238
- var projectName = "";
217
+ // slashCommands, cliSessionId -> store
218
+ var projectName = ""; // kept for pre-store localStorage init
239
219
  // turnCounter -> modules/app-rendering.js
240
220
 
241
221
  // Restore cached project name and icon for instant display (before WS connects)
@@ -257,13 +237,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
257
237
  }
258
238
  }
259
239
  } catch (e) {}
260
- var messageUuidMap = [];
261
- // pendingRewindUuid is now in modules/rewind.js
262
- // rewindMode is now in modules/rewind.js
263
-
264
- // --- Progressive history loading ---
265
- var historyFrom = 0;
266
- var historyTotal = 0;
240
+ // messageUuidMap, historyFrom, historyTotal -> store
267
241
  // prependAnchor, replayingHistory, isUserScrolledUp, scrollThreshold -> modules/app-rendering.js
268
242
  var loadingMore = false;
269
243
  // historySentinelObserver -> modules/app-header.js
@@ -279,12 +253,91 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
279
253
  function showConfirm(text, onConfirm, okLabel, destructive) { _miscShowConfirm(text, onConfirm, okLabel, destructive); }
280
254
  function hideConfirm() { _miscHideConfirm(); }
281
255
 
256
+ // --- Initialize store (single source of truth for client state) ---
257
+ createStore({
258
+ // session / routing
259
+ basePath: basePath,
260
+ wsPath: wsPath,
261
+ dmMode: false,
262
+ historyFrom: 0,
263
+ historyTotal: 0,
264
+ replayingHistory: false,
265
+ projectName: projectName,
266
+ currentSlug: currentSlug,
267
+ currentProjectOwnerId: null,
268
+ isOsUsers: false,
269
+ skipPermsEnabled: false,
270
+ slashCommands: [],
271
+ processing: false,
272
+ activeSessionId: null,
273
+ cliSessionId: null,
274
+ isHeadlessMode: false,
275
+ savedMainSlug: null,
276
+ connected: false,
277
+ // dm
278
+ dmTargetUser: null,
279
+ dmKey: null,
280
+ cachedMatesList: [],
281
+ cachedDmFavorites: [],
282
+ cachedAvailableBuiltins: [],
283
+ returningFromMateDm: false,
284
+ pendingMateInterview: null,
285
+ pendingTermCommand: null,
286
+ mateProjectSlug: null,
287
+ myUserId: null,
288
+ isMultiUserMode: false,
289
+ dmUnread: {},
290
+ dmRemovedUsers: {},
291
+ cachedAllUsers: [],
292
+ cachedOnlineIds: [],
293
+ cachedDmConversations: [],
294
+ sessionDrafts: {},
295
+ messageUuidMap: [],
296
+ // rendering
297
+ currentMsgTs: null,
298
+ richContextUsage: null,
299
+ currentMsgEl: null,
300
+ currentFullText: "",
301
+ matePreThinkingEl: null,
302
+ // panels
303
+ currentModel: "",
304
+ currentModels: [],
305
+ currentMode: "default",
306
+ currentEffort: "medium",
307
+ currentBetas: [],
308
+ currentThinking: "adaptive",
309
+ currentThinkingBudget: 10000,
310
+ ctxPopoverVisible: false,
311
+ headerContextEl: null,
312
+ // loop
313
+ loopActive: false,
314
+ loopAvailable: false,
315
+ loopIteration: 0,
316
+ loopMaxIterations: 0,
317
+ loopBannerName: null,
318
+ ralphPhase: "idle",
319
+ ralphCraftingSessionId: null,
320
+ ralphCraftingSource: null,
321
+ ralphFilesReady: { promptReady: false, judgeReady: false, bothReady: false },
322
+ ralphPreviewContent: { prompt: "", judge: "" },
323
+ execModalShown: false,
324
+ // debate
325
+ debateStickyState: null,
326
+ debateFloorMode: false,
327
+ debateConcludeMode: false,
328
+ debateEndedMode: false,
329
+ // skills
330
+ knownInstalledSkills: {},
331
+ // loop wizard
332
+ wizardData: { name: "", task: "", maxIterations: null, cron: null }
333
+ });
334
+
282
335
  // --- Rewind (module) ---
283
336
  initRewind({
284
337
  $: $,
285
338
  get ws() { return ws; },
286
- get connected() { return connected; },
287
- get processing() { return processing; },
339
+ get connected() { return store.getState().connected; },
340
+ get processing() { return store.getState().processing; },
288
341
  messagesEl: messagesEl,
289
342
  addSystemMessage: addSystemMessage,
290
343
  });
@@ -302,8 +355,8 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
302
355
  var sidebarCtx = {
303
356
  $: $,
304
357
  get ws() { return ws; },
305
- get connected() { return connected; },
306
- get projectName() { return projectName; },
358
+ get connected() { return store.getState().connected; },
359
+ get projectName() { return store.getState().projectName; },
307
360
  messagesEl: messagesEl,
308
361
  sessionListEl: sessionListEl,
309
362
  sidebar: sidebar,
@@ -322,18 +375,18 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
322
375
  showHomeHub: function () { showHomeHub(); },
323
376
  openRalphWizard: function (source) { openRalphWizard(source); },
324
377
  getUpcomingSchedules: getUpcomingSchedules,
325
- get multiUser() { return isMultiUserMode; },
326
- get myUserId() { return myUserId; },
327
- get projectOwnerId() { return currentProjectOwnerId; },
378
+ get multiUser() { return store.getState().isMultiUserMode; },
379
+ get myUserId() { return store.getState().myUserId; },
380
+ get projectOwnerId() { return store.getState().currentProjectOwnerId; },
328
381
  openDm: function (userId) { openDm(userId); },
329
382
  openMateWizard: function () { requireClayMateInterview(function () { openMateWizard(); }); },
330
383
  openAddProjectModal: function () { openAddProjectModal(); },
331
384
  sendWs: function (msg) { if (ws && ws.readyState === 1) ws.send(JSON.stringify(msg)); },
332
- onDmRemoveUser: function (userId) { dmRemovedUsers[userId] = true; },
333
- getHistoryFrom: function () { return historyFrom; },
385
+ onDmRemoveUser: function (userId) { var dr = Object.assign({}, store.getState().dmRemovedUsers); dr[userId] = true; store.setState({ dmRemovedUsers: dr }); },
386
+ getHistoryFrom: function () { return store.getState().historyFrom; },
334
387
  get permissions() { return myPermissions; },
335
388
  get projectList() { return getCachedProjects() || []; },
336
- availableBuiltins: function () { return cachedAvailableBuiltins || []; },
389
+ availableBuiltins: function () { return store.getState().cachedAvailableBuiltins || []; },
337
390
  };
338
391
  initSidebar(sidebarCtx);
339
392
  var wsGetter = function () { return ws; };
@@ -347,13 +400,13 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
347
400
 
348
401
  initCommandPalette({
349
402
  switchProject: function (slug) { switchProject(slug); },
350
- currentSlug: function () { return currentSlug; },
403
+ currentSlug: function () { return store.getState().currentSlug; },
351
404
  projectList: function () { return getCachedProjects() || []; },
352
- matesList: function () { return cachedMatesList || []; },
353
- availableBuiltins: function () { return cachedAvailableBuiltins || []; },
354
- allUsers: function () { return cachedAllUsers || []; },
355
- dmConversations: function () { return cachedDmConversations || []; },
356
- myUserId: function () { return myUserId; },
405
+ matesList: function () { return store.getState().cachedMatesList || []; },
406
+ availableBuiltins: function () { return store.getState().cachedAvailableBuiltins || []; },
407
+ allUsers: function () { return store.getState().cachedAllUsers || []; },
408
+ dmConversations: function () { return store.getState().cachedDmConversations || []; },
409
+ myUserId: function () { return store.getState().myUserId; },
357
410
  selectSession: function (id) {
358
411
  // Close any open panels before switching
359
412
  if (isSchedulerOpen()) closeScheduler();
@@ -408,8 +461,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
408
461
  // currentModels, currentModel, currentMode, currentEffort, currentBetas,
409
462
  // currentThinking, currentThinkingBudget, sessionUsage, contextData,
410
463
  // headerContextEl, richContextUsage, ctxPopoverVisible -> modules/app-panels.js
411
- var skipPermsEnabled = false;
412
- var isOsUsers = false;
464
+ // skipPermsEnabled, isOsUsers -> store
413
465
 
414
466
  function updateConfigChip() { _panUpdateConfigChip(); }
415
467
  function getModelEffortLevels() { return _panGetModelEffortLevels(); }
@@ -479,11 +531,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
479
531
  function forceScrollToBottom() { _renForceScrollToBottom(); }
480
532
 
481
533
  // --- Misc module (modals, PWA, extension bridge, force PIN) ---
482
- initMisc({
483
- $: $,
484
- getWs: function () { return ws; },
485
- updateBrowserTabList: updateBrowserTabList,
486
- });
534
+ initMisc();
487
535
 
488
536
  // --- Favicon module ---
489
537
  initFavicon({
@@ -495,10 +543,10 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
495
543
  scrollToBottom: scrollToBottom,
496
544
  getActivityEl: getActivityEl,
497
545
  setActivityEl: setActivityEl,
498
- get connected() { return connected; },
499
- get dmMode() { return dmMode; },
500
- get dmTargetUser() { return dmTargetUser; },
501
- get currentSlug() { return currentSlug; },
546
+ get connected() { return store.getState().connected; },
547
+ get dmMode() { return store.getState().dmMode; },
548
+ get dmTargetUser() { return store.getState().dmTargetUser; },
549
+ get currentSlug() { return store.getState().currentSlug; },
502
550
  });
503
551
 
504
552
  // --- Header module (rename, info popover, history) ---
@@ -509,17 +557,19 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
509
557
  headerRenameBtn: headerRenameBtn,
510
558
  headerInfoBtn: $("header-info-btn"),
511
559
  getWs: function () { return ws; },
512
- get connected() { return connected; },
513
- get activeSessionId() { return activeSessionId; },
514
- get cliSessionId() { return cliSessionId; },
515
- get historyFrom() { return historyFrom; },
516
- set historyFrom(v) { historyFrom = v; },
560
+ get connected() { return store.getState().connected; },
561
+ get activeSessionId() { return store.getState().activeSessionId; },
562
+ get cliSessionId() { return store.getState().cliSessionId; },
563
+ get historyFrom() { return store.getState().historyFrom; },
564
+ set historyFrom(v) { store.setState({ historyFrom: v }); },
517
565
  get loadingMore() { return loadingMore; },
518
566
  set loadingMore(v) { loadingMore = v; },
519
567
  // Rendering state accessors for prependOlderHistory
520
- getCurrentMsgEl: getCurrentMsgEl, setCurrentMsgEl: setCurrentMsgEl,
568
+ getCurrentMsgEl: function () { return store.getState().currentMsgEl; },
569
+ setCurrentMsgEl: function (v) { store.setState({ currentMsgEl: v }); },
521
570
  getActivityEl: getActivityEl, setActivityEl: setActivityEl,
522
- getCurrentFullText: getCurrentFullText, setCurrentFullText: setCurrentFullText,
571
+ getCurrentFullText: function () { return store.getState().currentFullText; },
572
+ setCurrentFullText: function (v) { store.setState({ currentFullText: v }); },
523
573
  getTurnCounter: getTurnCounter, setTurnCounter: setTurnCounter,
524
574
  saveToolState: saveToolState, resetToolState: resetToolState, restoreToolState: restoreToolState,
525
575
  getContextData: getContextData, setContextData: setContextData,
@@ -533,60 +583,19 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
533
583
  });
534
584
 
535
585
  // --- Skill Install module ---
536
- initSkillInstall({
537
- get basePath() { return basePath; },
538
- });
586
+ initSkillInstall();
539
587
 
540
588
  // --- Debate UI module ---
541
- initDebateUi({
542
- getWs: function () { return ws; },
543
- inputEl: inputEl,
544
- messagesEl: messagesEl,
545
- scrollToBottom: scrollToBottom,
546
- exportDebateAsPdf: exportDebateAsPdf,
547
- });
548
-
549
- // --- Loop UI module ---
550
- var loopUiCtx = {
551
- getWs: function () { return ws; },
552
- get activeSessionId() { return activeSessionId; },
553
- get basePath() { return basePath; },
554
- showConfirm: showConfirm,
555
- requireSkills: requireSkills,
556
- openSchedulerToTab: openSchedulerToTab,
557
- openRalphWizard: openRalphWizard,
558
- showDebateSticky: showDebateSticky,
559
- get debateStickyState() { return getDebateStickyState(); },
560
- getWizardData: function () { return getWizardData(); },
561
- getExecModalShown: function () { return getExecModalShown(); },
562
- setExecModalShown: function (v) { setExecModalShown(v); },
563
- };
564
- initLoopUi(loopUiCtx);
589
+ initDebateUi();
565
590
 
566
- initLoopWizard({
567
- getWs: function () { return ws; },
568
- requireSkills: requireSkills,
569
- setExecModalShown: function (v) { setExecModalShown(v); },
570
- });
591
+ initLoopUi();
592
+ initLoopWizard();
571
593
 
572
594
  // --- Notifications module ---
573
- initAppNotifications({
574
- getWs: function () { return ws; },
575
- openDm: function (mateId) { if (typeof openDm === "function") openDm(mateId); },
576
- getCachedProjects: function () { return getCachedProjects(); },
577
- getActiveSessionId: function () { return activeSessionId; },
578
- getCurrentSlug: function () { return currentSlug; },
579
- switchProject: function (s) { if (typeof switchProject === "function") switchProject(s); },
580
- });
595
+ initAppNotifications();
581
596
 
582
597
  // --- Panels module ---
583
- initPanels({
584
- $: $,
585
- getWs: function () { return ws; },
586
- get skipPermsEnabled() { return skipPermsEnabled; },
587
- getReplayingHistory: function () { return getReplayingHistory(); },
588
- refreshIcons: refreshIcons,
589
- });
598
+ initPanels();
590
599
 
591
600
  // --- Rendering module ---
592
601
  initRendering({
@@ -615,18 +624,18 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
615
624
  openTerminal: function () { openTerminal(); },
616
625
  getChatLayout: getChatLayout,
617
626
  getWs: function () { return ws; },
618
- getDmTargetUser: function () { return dmTargetUser; },
619
- setPendingTermCommand: function (v) { pendingTermCommand = v; },
620
- getProcessing: function () { return processing; },
621
- get myUserId() { return myUserId; },
622
- get cachedAllUsers() { return cachedAllUsers; },
627
+ getDmTargetUser: function () { return store.getState().dmTargetUser; },
628
+ setPendingTermCommand: function (v) { store.setState({ pendingTermCommand: v }); },
629
+ getProcessing: function () { return store.getState().processing; },
630
+ get myUserId() { return store.getState().myUserId; },
631
+ get cachedAllUsers() { return store.getState().cachedAllUsers; },
623
632
  });
624
633
 
625
634
  // --- Tools module ---
626
635
  initTools({
627
636
  $: $,
628
637
  get ws() { return ws; },
629
- get connected() { return connected; },
638
+ get connected() { return store.getState().connected; },
630
639
  get turnCounter() { return getTurnCounter(); },
631
640
  messagesEl: messagesEl,
632
641
  inputEl: inputEl,
@@ -640,14 +649,15 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
640
649
  var cd = getContextData();
641
650
  return cd.contextWindow > 0 ? Math.round((cd.input / cd.contextWindow) * 100) : 0;
642
651
  },
643
- isMateDm: function () { return dmMode && dmTargetUser && dmTargetUser.isMate; },
644
- getMateName: function () { return dmTargetUser ? (dmTargetUser.displayName || "Mate") : "Mate"; },
652
+ isMateDm: function () { return store.getState().dmMode && store.getState().dmTargetUser && store.getState().dmTargetUser.isMate; },
653
+ getMateName: function () { return store.getState().dmTargetUser ? (store.getState().dmTargetUser.displayName || "Mate") : "Mate"; },
645
654
  getMateAvatarUrl: function () { return document.body.dataset.mateAvatarUrl || ""; },
646
655
  getClaudeAvatar: function () { return CLAUDE_CODE_AVATAR; },
647
656
  getMateById: function (id) {
648
- if (!id || !cachedMatesList) return null;
649
- for (var i = 0; i < cachedMatesList.length; i++) {
650
- if (cachedMatesList[i].id === id) return cachedMatesList[i];
657
+ var ml = store.getState().cachedMatesList;
658
+ if (!id || !ml) return null;
659
+ for (var i = 0; i < ml.length; i++) {
660
+ if (ml[i].id === id) return ml[i];
651
661
  }
652
662
  return null;
653
663
  },
@@ -670,8 +680,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
670
680
  function addConflictMessage(msg) { _renAddConflictMessage(msg); }
671
681
  function addContextOverflowMessage(msg) { _renAddContextOverflowMessage(msg); }
672
682
 
673
- // Pending command to run in the next created terminal
674
- var pendingTermCommand = null;
683
+ // pendingTermCommand -> store
675
684
 
676
685
  function addAuthRequiredMessage(msg) { _renAddAuthRequiredMessage(msg); }
677
686
 
@@ -696,14 +705,15 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
696
705
  window.addEventListener("popstate", function () {
697
706
  var m = location.pathname.match(/^\/p\/([a-z0-9_-]+)/);
698
707
  var newSlug = m ? m[1] : null;
699
- if (newSlug && newSlug !== currentSlug) {
708
+ if (newSlug && newSlug !== store.getState().currentSlug) {
700
709
  resetFileBrowser();
701
710
  closeArchive();
702
711
  if (isSchedulerOpen()) closeScheduler();
703
712
  resetScheduler(newSlug);
704
- currentSlug = newSlug;
713
+ store.setState({ currentSlug: newSlug });
705
714
  basePath = "/p/" + newSlug + "/";
706
715
  wsPath = "/p/" + newSlug + "/ws";
716
+ store.setState({ basePath: basePath, wsPath: wsPath });
707
717
  resetClientState();
708
718
  connect();
709
719
  }
@@ -728,16 +738,16 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
728
738
  // --- Input module (sendMessage, autoResize, paste/image, slash menu, input handlers) ---
729
739
  initInput({
730
740
  get ws() { return ws; },
731
- get connected() { return connected; },
732
- get processing() { return processing; },
741
+ get connected() { return store.getState().connected; },
742
+ get processing() { return store.getState().processing; },
733
743
  get basePath() { return basePath; },
734
744
  inputEl: inputEl,
735
745
  sendBtn: sendBtn,
736
746
  slashMenu: slashMenu,
737
747
  messagesEl: messagesEl,
738
748
  imagePreviewBar: imagePreviewBar,
739
- slashCommands: function() { return slashCommands; },
740
- messageUuidMap: function() { return messageUuidMap; },
749
+ slashCommands: function() { return store.getState().slashCommands; },
750
+ messageUuidMap: function() { return store.getState().messageUuidMap; },
741
751
  addUserMessage: addUserMessage,
742
752
  addSystemMessage: addSystemMessage,
743
753
  toggleUsagePanel: toggleUsagePanel,
@@ -747,18 +757,18 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
747
757
  showImageModal: showImageModal,
748
758
  hideSuggestionChips: hideSuggestionChips,
749
759
  setSendBtnMode: setSendBtnMode,
750
- isDmMode: function () { return dmMode && !(dmTargetUser && dmTargetUser.isMate); },
751
- getDmKey: function () { return dmKey; },
760
+ isDmMode: function () { return store.getState().dmMode && !(store.getState().dmTargetUser && store.getState().dmTargetUser.isMate); },
761
+ getDmKey: function () { return store.getState().dmKey; },
752
762
  handleDmSend: function () { handleDmSend(); },
753
- isDebateEndedMode: function () { return getDebateEndedMode(); },
763
+ isDebateEndedMode: function () { return store.getState().debateEndedMode; },
754
764
  handleDebateEndedSend: function () { handleDebateEndedSend(); },
755
- isDebateConcludeMode: function () { return getDebateConcludeMode(); },
765
+ isDebateConcludeMode: function () { return store.getState().debateConcludeMode; },
756
766
  handleDebateConcludeSend: function () { handleDebateConcludeSend(); },
757
- isDebateFloorMode: function () { return getDebateFloorMode(); },
767
+ isDebateFloorMode: function () { return store.getState().debateFloorMode; },
758
768
  handleDebateFloorSend: function () { handleDebateFloorSend(); },
759
- isMateDm: function () { return dmMode && dmTargetUser && dmTargetUser.isMate; },
760
- getDmMateId: function () { return (dmMode && dmTargetUser && dmTargetUser.isMate) ? dmTargetUser.id : null; },
761
- getMateName: function () { return dmTargetUser ? (dmTargetUser.displayName || "Mate") : "Mate"; },
769
+ isMateDm: function () { return store.getState().dmMode && store.getState().dmTargetUser && store.getState().dmTargetUser.isMate; },
770
+ getDmMateId: function () { return (store.getState().dmMode && store.getState().dmTargetUser && store.getState().dmTargetUser.isMate) ? dmTargetUser.id : null; },
771
+ getMateName: function () { return store.getState().dmTargetUser ? (store.getState().dmTargetUser.displayName || "Mate") : "Mate"; },
762
772
  getMateAvatarUrl: function () { return document.body.dataset.mateAvatarUrl || ""; },
763
773
  showMatePreThinking: function () { showMatePreThinking(); },
764
774
  showClaudePreThinking: function () { showClaudePreThinking(); },
@@ -767,11 +777,11 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
767
777
  // --- @Mention module ---
768
778
  initMention({
769
779
  get ws() { return ws; },
770
- get connected() { return connected; },
780
+ get connected() { return store.getState().connected; },
771
781
  inputEl: inputEl,
772
782
  messagesEl: messagesEl,
773
- matesList: function () { return cachedMatesList || []; },
774
- availableBuiltins: function () { return cachedAvailableBuiltins || []; },
783
+ matesList: function () { return store.getState().cachedMatesList || []; },
784
+ availableBuiltins: function () { return store.getState().cachedAvailableBuiltins || []; },
775
785
  scrollToBottom: scrollToBottom,
776
786
  addUserMessage: addUserMessage,
777
787
  addCopyHandler: addCopyHandler,
@@ -788,9 +798,9 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
788
798
  addToMessages: function (el) { addToMessages(el); },
789
799
  scrollToBottom: scrollToBottom,
790
800
  addCopyHandler: addCopyHandler,
791
- matesList: function () { return cachedMatesList || []; },
792
- availableBuiltins: function () { return cachedAvailableBuiltins || []; },
793
- currentMateId: function () { return (dmTargetUser && dmTargetUser.isMate) ? dmTargetUser.id : null; },
801
+ matesList: function () { return store.getState().cachedMatesList || []; },
802
+ availableBuiltins: function () { return store.getState().cachedAvailableBuiltins || []; },
803
+ currentMateId: function () { return (store.getState().dmTargetUser && store.getState().dmTargetUser.isMate) ? store.getState().dmTargetUser.id : null; },
794
804
  requireSkills: requireSkills,
795
805
  showDebateEndedMode: function (msg) { showDebateEndedMode(msg); },
796
806
  });
@@ -816,20 +826,18 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
816
826
  function showForceChangePinOverlay() { _miscShowForceChangePinOverlay(); }
817
827
 
818
828
  // --- Admin (multi-user mode) ---
819
- var isMultiUserMode = false;
820
- var isHeadlessMode = false;
821
- var myUserId = null;
829
+ // isMultiUserMode, isHeadlessMode, myUserId -> store
822
830
  initAdmin({
823
831
  get projectList() { return getCachedProjects(); },
824
832
  });
825
833
  var myPermissions = null; // null = single-user, all allowed
826
834
  fetch("/api/me").then(function (r) { return r.json(); }).then(function (d) {
827
- if (d.multiUser) isMultiUserMode = true;
828
- if (d.user && d.user.id) myUserId = d.user.id;
835
+ if (d.multiUser) { store.setState({ isMultiUserMode: true }); }
836
+ if (d.user && d.user.id) { store.setState({ myUserId: d.user.id }); }
829
837
  if (d.permissions) myPermissions = d.permissions;
830
838
  if (d.mustChangePin) showForceChangePinOverlay();
831
839
  // Single-user mode: clear user strip skeletons immediately (no presence message will arrive)
832
- if (!isMultiUserMode) {
840
+ if (!store.getState().isMultiUserMode) {
833
841
  var usersContainer = document.getElementById("icon-strip-users");
834
842
  if (usersContainer) {
835
843
  usersContainer.innerHTML = "";
@@ -869,7 +877,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
869
877
  }).catch(function () {});
870
878
  // Hide server settings and update controls for non-admin users in multi-user mode
871
879
  checkAdminAccess().then(function (isAdmin) {
872
- if (isMultiUserMode && !isAdmin) {
880
+ if (store.getState().isMultiUserMode && !isAdmin) {
873
881
  var settingsBtn = document.getElementById("server-settings-btn");
874
882
  if (settingsBtn) settingsBtn.style.display = "none";
875
883
  var updatePill = document.getElementById("update-pill-wrap");
@@ -881,7 +889,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
881
889
  initNotifications({
882
890
  $: $,
883
891
  get ws() { return ws; },
884
- get connected() { return connected; },
892
+ get connected() { return store.getState().connected; },
885
893
  messagesEl: messagesEl,
886
894
  sessionListEl: sessionListEl,
887
895
  scrollToBottom: scrollToBottom,
@@ -893,17 +901,17 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
893
901
  // --- Server Settings ---
894
902
  initServerSettings({
895
903
  get ws() { return ws; },
896
- get projectName() { return projectName; },
897
- get currentSlug() { return currentSlug; },
904
+ get projectName() { return store.getState().projectName; },
905
+ get currentSlug() { return store.getState().currentSlug; },
898
906
  wsPath: wsPath,
899
- get currentModels() { return getCurrentModels(); },
900
- set currentModels(v) { setCurrentModels(v); updateConfigChip(); },
901
- get currentModel() { return getCurrentModel(); },
902
- get currentMode() { return getCurrentMode(); },
903
- get currentEffort() { return getCurrentEffort(); },
904
- get currentBetas() { return getCurrentBetas(); },
905
- get currentThinking() { return getCurrentThinking(); },
906
- get currentThinkingBudget() { return getCurrentThinkingBudget(); },
907
+ get currentModels() { return store.getState().currentModels; },
908
+ set currentModels(v) { store.setState({ currentModels: v }); updateConfigChip(); },
909
+ get currentModel() { return store.getState().currentModel; },
910
+ get currentMode() { return store.getState().currentMode; },
911
+ get currentEffort() { return store.getState().currentEffort; },
912
+ get currentBetas() { return store.getState().currentBetas; },
913
+ get currentThinking() { return store.getState().currentThinking; },
914
+ get currentThinkingBudget() { return store.getState().currentThinkingBudget; },
907
915
  setContextView: function (v) { _panSetContextView(v); },
908
916
  applyContextView: function (v) { _panApplyContextView(v); },
909
917
  });
@@ -911,14 +919,14 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
911
919
  // --- Project Settings ---
912
920
  initProjectSettings({
913
921
  get ws() { return ws; },
914
- get connected() { return connected; },
915
- get currentModels() { return getCurrentModels(); },
916
- get currentModel() { return getCurrentModel(); },
917
- get currentMode() { return getCurrentMode(); },
918
- get currentEffort() { return getCurrentEffort(); },
919
- get currentBetas() { return getCurrentBetas(); },
920
- get currentThinking() { return getCurrentThinking(); },
921
- get currentThinkingBudget() { return getCurrentThinkingBudget(); },
922
+ get connected() { return store.getState().connected; },
923
+ get currentModels() { return store.getState().currentModels; },
924
+ get currentModel() { return store.getState().currentModel; },
925
+ get currentMode() { return store.getState().currentMode; },
926
+ get currentEffort() { return store.getState().currentEffort; },
927
+ get currentBetas() { return store.getState().currentBetas; },
928
+ get currentThinking() { return store.getState().currentThinking; },
929
+ get currentThinkingBudget() { return store.getState().currentThinkingBudget; },
922
930
  }, getEmojiCategories());
923
931
 
924
932
  // --- QR code ---
@@ -929,8 +937,8 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
929
937
  // --- File browser ---
930
938
  initFileBrowser({
931
939
  get ws() { return ws; },
932
- get connected() { return connected; },
933
- get activeSessionId() { return activeSessionId; },
940
+ get connected() { return store.getState().connected; },
941
+ get activeSessionId() { return store.getState().activeSessionId; },
934
942
  messagesEl: messagesEl,
935
943
  fileTreeEl: $("file-tree"),
936
944
  fileViewerEl: $("file-viewer"),
@@ -939,7 +947,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
939
947
  // --- Terminal ---
940
948
  initTerminal({
941
949
  get ws() { return ws; },
942
- get connected() { return connected; },
950
+ get connected() { return store.getState().connected; },
943
951
  terminalContainerEl: $("terminal-container"),
944
952
  terminalBodyEl: $("terminal-body"),
945
953
  fileViewerEl: $("file-viewer"),
@@ -948,7 +956,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
948
956
  // --- Context Sources ---
949
957
  initContextSources({
950
958
  get ws() { return ws; },
951
- get connected() { return connected; },
959
+ get connected() { return store.getState().connected; },
952
960
  });
953
961
 
954
962
  // --- Chrome Extension Bridge -> modules/app-misc.js
@@ -977,7 +985,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
977
985
  initSessionSearch({
978
986
  messagesEl: messagesEl,
979
987
  get ws() { return ws; },
980
- getHistoryFrom: function () { return historyFrom; },
988
+ getHistoryFrom: function () { return store.getState().historyFrom; },
981
989
  });
982
990
  var findInSessionBtn = $("find-in-session-btn");
983
991
  if (findInSessionBtn) {
@@ -989,7 +997,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
989
997
  // --- Sticky Notes ---
990
998
  initStickyNotes({
991
999
  get ws() { return ws; },
992
- get connected() { return connected; },
1000
+ get connected() { return store.getState().connected; },
993
1001
  });
994
1002
 
995
1003
  // --- Sticky Notes sidebar button (archive view) ---
@@ -1043,7 +1051,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
1043
1051
  if (debateBtn) {
1044
1052
  debateBtn.addEventListener("click", function () {
1045
1053
  var contextMessages = dmMessageCache.map(function (m) {
1046
- return { text: m.text, isMate: m.from !== myUserId };
1054
+ return { text: m.text, isMate: m.from !== store.getState().myUserId };
1047
1055
  });
1048
1056
  openDebateModal({ dmContext: contextMessages });
1049
1057
  });
@@ -1075,7 +1083,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
1075
1083
  // --- Skills ---
1076
1084
  initSkills({
1077
1085
  get ws() { return ws; },
1078
- get connected() { return connected; },
1086
+ get connected() { return store.getState().connected; },
1079
1087
  basePath: basePath,
1080
1088
  openTerminal: function () { openTerminal(); },
1081
1089
  sendTerminalCommand: function (cmd) { sendTerminalCommand(cmd); },
@@ -1084,10 +1092,10 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
1084
1092
  // --- Scheduler ---
1085
1093
  initScheduler({
1086
1094
  get ws() { return ws; },
1087
- get connected() { return connected; },
1088
- get activeSessionId() { return activeSessionId; },
1095
+ get connected() { return store.getState().connected; },
1096
+ get activeSessionId() { return store.getState().activeSessionId; },
1089
1097
  basePath: basePath,
1090
- currentSlug: currentSlug,
1098
+ currentSlug: currentSlug, // init-time snapshot, scheduler uses for initial setup
1091
1099
  openRalphWizard: function (source) { openRalphWizard(source); },
1092
1100
  requireClayRalph: function (cb) {
1093
1101
  requireSkills({
@@ -1123,22 +1131,11 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
1123
1131
  messagesEl: messagesEl,
1124
1132
  registerTooltip: registerTooltip,
1125
1133
  get ws() { return ws; },
1126
- get isMultiUserMode() { return isMultiUserMode; },
1134
+ get isMultiUserMode() { return store.getState().isMultiUserMode; },
1127
1135
  });
1128
1136
 
1129
1137
  // --- Rate Limit module ---
1130
- initRateLimit({
1131
- iconHtml: iconHtml,
1132
- refreshIcons: refreshIcons,
1133
- addToMessages: addToMessages,
1134
- scrollToBottom: scrollToBottom,
1135
- userAvatarUrl: userAvatarUrl,
1136
- setScheduleDelayMs: setScheduleDelayMs,
1137
- clearScheduleDelay: clearScheduleDelay,
1138
- get ws() { return ws; },
1139
- get cachedAllUsers() { return cachedAllUsers; },
1140
- get myUserId() { return myUserId; },
1141
- });
1138
+ initRateLimit();
1142
1139
 
1143
1140
  // --- Projects module ---
1144
1141
  initProjects({
@@ -1159,8 +1156,8 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
1159
1156
  spawnDustParticles: spawnDustParticles,
1160
1157
  getStatusDot: getStatusDot,
1161
1158
  // Rendering state accessors
1162
- setCurrentMsgEl: setCurrentMsgEl,
1163
- setCurrentFullText: setCurrentFullText,
1159
+ setCurrentMsgEl: function (v) { store.setState({ currentMsgEl: v }); },
1160
+ setCurrentFullText: function (v) { store.setState({ currentFullText: v }); },
1164
1161
  setTurnCounter: setTurnCounter,
1165
1162
  setPrependAnchor: setPrependAnchor,
1166
1163
  setActivityEl: setActivityEl,
@@ -1193,42 +1190,42 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
1193
1190
  connect: function () { connect(); },
1194
1191
  cancelReconnect: function () { _connCancelReconnect(); },
1195
1192
  getWs: function () { return ws; },
1196
- setWs: function (v) { ws = v; },
1197
- setConnected: function (v) { connected = v; },
1198
- setProcessing: function (v) { processing = v; },
1199
- setCurrentSlug: function (v) { currentSlug = v; },
1193
+ setWs: function (v) { ws = v; _setWsRef(v); },
1194
+ setConnected: function (v) { store.setState({ connected: v }); },
1195
+ setProcessing: function (v) { store.setState({ processing: v }); },
1196
+ setCurrentSlug: function (v) { store.setState({ currentSlug: v }); },
1200
1197
  setBasePath: function (v) { basePath = v; },
1201
1198
  setWsPath: function (v) { wsPath = v; },
1202
- setMessageUuidMap: function (v) { messageUuidMap = v; },
1203
- setHistoryFrom: function (v) { historyFrom = v; },
1204
- setHistoryTotal: function (v) { historyTotal = v; },
1199
+ setMessageUuidMap: function (v) { store.setState({ messageUuidMap: v }); },
1200
+ setHistoryFrom: function (v) { store.setState({ historyFrom: v }); },
1201
+ setHistoryTotal: function (v) { store.setState({ historyTotal: v }); },
1205
1202
  setLoadingMore: function (v) { loadingMore = v; },
1206
- getHeaderContextEl: function () { return _panGetHeaderContextEl(); },
1207
- setHeaderContextEl: function (v) { _panSetHeaderContextEl(v); },
1208
- setDebateStickyState: function (v) { setDebateStickyState(v); },
1209
- setCachedOnlineIds: function (v) { cachedOnlineIds = v; },
1210
- setCachedAllUsers: function (v) { cachedAllUsers = v; },
1211
- setCachedDmFavorites: function (v) { cachedDmFavorites = v; },
1212
- setCachedDmConversations: function (v) { cachedDmConversations = v; },
1213
- get currentSlug() { return currentSlug; },
1214
- get connected() { return connected; },
1215
- get processing() { return processing; },
1216
- get loopActive() { return getLoopActive(); },
1217
- get dmMode() { return dmMode; },
1218
- get dmTargetUser() { return dmTargetUser; },
1219
- get activeSessionId() { return activeSessionId; },
1220
- get isHeadlessMode() { return isHeadlessMode; },
1221
- get isOsUsers() { return isOsUsers; },
1222
- get mateProjectSlug() { return mateProjectSlug; },
1223
- get savedMainSlug() { return savedMainSlug; },
1224
- get myUserId() { return myUserId; },
1225
- get cachedAllUsers() { return cachedAllUsers; },
1226
- get cachedOnlineIds() { return cachedOnlineIds; },
1227
- get cachedDmFavorites() { return cachedDmFavorites; },
1228
- get cachedDmConversations() { return cachedDmConversations; },
1229
- get dmUnread() { return dmUnread; },
1230
- get dmRemovedUsers() { return dmRemovedUsers; },
1231
- get cachedMatesList() { return cachedMatesList; },
1203
+ getHeaderContextEl: function () { return store.getState().headerContextEl; },
1204
+ setHeaderContextEl: function (v) { store.setState({ headerContextEl: v }); },
1205
+ setDebateStickyState: function (v) { store.setState({ debateStickyState: v }); },
1206
+ setCachedOnlineIds: function (v) { store.setState({ cachedOnlineIds: v }); },
1207
+ setCachedAllUsers: function (v) { store.setState({ cachedAllUsers: v }); },
1208
+ setCachedDmFavorites: function (v) { store.setState({ cachedDmFavorites: v }); },
1209
+ setCachedDmConversations: function (v) { store.setState({ cachedDmConversations: v }); },
1210
+ get currentSlug() { return store.getState().currentSlug; },
1211
+ get connected() { return store.getState().connected; },
1212
+ get processing() { return store.getState().processing; },
1213
+ get loopActive() { return store.getState().loopActive; },
1214
+ get dmMode() { return store.getState().dmMode; },
1215
+ get dmTargetUser() { return store.getState().dmTargetUser; },
1216
+ get activeSessionId() { return store.getState().activeSessionId; },
1217
+ get isHeadlessMode() { return store.getState().isHeadlessMode; },
1218
+ get isOsUsers() { return store.getState().isOsUsers; },
1219
+ get mateProjectSlug() { return store.getState().mateProjectSlug; },
1220
+ get savedMainSlug() { return store.getState().savedMainSlug; },
1221
+ get myUserId() { return store.getState().myUserId; },
1222
+ get cachedAllUsers() { return store.getState().cachedAllUsers; },
1223
+ get cachedOnlineIds() { return store.getState().cachedOnlineIds; },
1224
+ get cachedDmFavorites() { return store.getState().cachedDmFavorites; },
1225
+ get cachedDmConversations() { return store.getState().cachedDmConversations; },
1226
+ get dmUnread() { return store.getState().dmUnread; },
1227
+ get dmRemovedUsers() { return store.getState().dmRemovedUsers; },
1228
+ get cachedMatesList() { return store.getState().cachedMatesList; },
1232
1229
  });
1233
1230
 
1234
1231
  // --- Home Hub module ---
@@ -1244,11 +1241,11 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
1244
1241
  openPlaybook: openPlaybook,
1245
1242
  getPlaybookForTip: getPlaybookForTip,
1246
1243
  renderProjectList: renderProjectList,
1247
- get dmMode() { return dmMode; },
1244
+ get dmMode() { return store.getState().dmMode; },
1248
1245
  get ws() { return ws; },
1249
- get currentSlug() { return currentSlug; },
1246
+ get currentSlug() { return store.getState().currentSlug; },
1250
1247
  get cachedProjects() { return getCachedProjects(); },
1251
- get cachedMatesList() { return cachedMatesList; },
1248
+ get cachedMatesList() { return store.getState().cachedMatesList; },
1252
1249
  });
1253
1250
 
1254
1251
  // --- DM module ---
@@ -1284,393 +1281,43 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
1284
1281
  messagesEl: messagesEl,
1285
1282
  inputEl: inputEl,
1286
1283
  };
1287
- // Mutable state for DM module
1288
- var _dmStateProps = {
1289
- ws: function() { return ws; },
1290
- dmMode: function() { return dmMode; }, _dmMode: function(v) { dmMode = v; },
1291
- dmKey: function() { return dmKey; }, _dmKey: function(v) { dmKey = v; },
1292
- dmTargetUser: function() { return dmTargetUser; }, _dmTargetUser: function(v) { dmTargetUser = v; },
1293
- dmMessageCache: function() { return dmMessageCache; }, _dmMessageCache: function(v) { dmMessageCache = v; },
1294
- dmUnread: function() { return dmUnread; },
1295
- dmRemovedUsers: function() { return dmRemovedUsers; },
1296
- cachedAllUsers: function() { return cachedAllUsers; },
1297
- cachedOnlineIds: function() { return cachedOnlineIds; },
1298
- cachedDmFavorites: function() { return cachedDmFavorites; }, _cachedDmFavorites: function(v) { cachedDmFavorites = v; },
1299
- cachedDmConversations: function() { return cachedDmConversations; },
1300
- cachedMatesList: function() { return cachedMatesList; },
1301
- cachedAvailableBuiltins: function() { return cachedAvailableBuiltins; }, _cachedAvailableBuiltins: function(v) { cachedAvailableBuiltins = v; },
1302
- cachedProjects: function() { return getCachedProjects(); },
1303
- mateProjectSlug: function() { return mateProjectSlug; }, _mateProjectSlug: function(v) { mateProjectSlug = v; },
1304
- savedMainSlug: function() { return savedMainSlug; }, _savedMainSlug: function(v) { savedMainSlug = v; },
1305
- returningFromMateDm: function() { return returningFromMateDm; }, _returningFromMateDm: function(v) { returningFromMateDm = v; },
1306
- pendingMateInterview: function() { return pendingMateInterview; }, _pendingMateInterview: function(v) { pendingMateInterview = v; },
1307
- currentSlug: function() { return currentSlug; }, _currentSlug: function(v) { currentSlug = v; },
1308
- wsPath: function() { return wsPath; }, _wsPath: function(v) { wsPath = v; },
1309
- basePath: function() { return basePath; }, _basePath: function(v) { basePath = v; },
1310
- activeSessionId: function() { return activeSessionId; },
1311
- myUserId: function() { return myUserId; },
1312
- };
1313
- Object.keys(_dmStateProps).forEach(function(key) {
1314
- if (key.charAt(0) === "_") return;
1315
- var getter = _dmStateProps[key];
1316
- var setter = _dmStateProps["_" + key];
1317
- var desc = { get: getter, enumerable: true };
1318
- if (setter) desc.set = setter;
1319
- Object.defineProperty(_dmCtx, key, desc);
1284
+ // Mutable state for DM module (store-backed)
1285
+ Object.defineProperties(_dmCtx, {
1286
+ ws: { get: function() { return ws; }, enumerable: true },
1287
+ dmMode: { get: function() { return store.getState().dmMode; }, set: function(v) { store.setState({ dmMode: v }); }, enumerable: true },
1288
+ dmKey: { get: function() { return store.getState().dmKey; }, set: function(v) { store.setState({ dmKey: v }); }, enumerable: true },
1289
+ dmTargetUser: { get: function() { return store.getState().dmTargetUser; }, set: function(v) { store.setState({ dmTargetUser: v }); }, enumerable: true },
1290
+ dmMessageCache: { get: function() { return dmMessageCache; }, set: function(v) { dmMessageCache = v; }, enumerable: true },
1291
+ dmUnread: { get: function() { return store.getState().dmUnread; }, enumerable: true },
1292
+ dmRemovedUsers: { get: function() { return store.getState().dmRemovedUsers; }, enumerable: true },
1293
+ cachedAllUsers: { get: function() { return store.getState().cachedAllUsers; }, enumerable: true },
1294
+ cachedOnlineIds: { get: function() { return store.getState().cachedOnlineIds; }, enumerable: true },
1295
+ cachedDmFavorites: { get: function() { return store.getState().cachedDmFavorites; }, set: function(v) { store.setState({ cachedDmFavorites: v }); }, enumerable: true },
1296
+ cachedDmConversations: { get: function() { return store.getState().cachedDmConversations; }, enumerable: true },
1297
+ cachedMatesList: { get: function() { return store.getState().cachedMatesList; }, enumerable: true },
1298
+ cachedAvailableBuiltins: { get: function() { return store.getState().cachedAvailableBuiltins; }, set: function(v) { store.setState({ cachedAvailableBuiltins: v }); }, enumerable: true },
1299
+ cachedProjects: { get: function() { return getCachedProjects(); }, enumerable: true },
1300
+ mateProjectSlug: { get: function() { return store.getState().mateProjectSlug; }, set: function(v) { store.setState({ mateProjectSlug: v }); }, enumerable: true },
1301
+ savedMainSlug: { get: function() { return store.getState().savedMainSlug; }, set: function(v) { store.setState({ savedMainSlug: v }); }, enumerable: true },
1302
+ returningFromMateDm: { get: function() { return store.getState().returningFromMateDm; }, set: function(v) { store.setState({ returningFromMateDm: v }); }, enumerable: true },
1303
+ pendingMateInterview: { get: function() { return store.getState().pendingMateInterview; }, set: function(v) { store.setState({ pendingMateInterview: v }); }, enumerable: true },
1304
+ currentSlug: { get: function() { return store.getState().currentSlug; }, set: function(v) { store.setState({ currentSlug: v }); }, enumerable: true },
1305
+ wsPath: { get: function() { return wsPath; }, set: function(v) { wsPath = v; }, enumerable: true },
1306
+ basePath: { get: function() { return basePath; }, set: function(v) { basePath = v; }, enumerable: true },
1307
+ activeSessionId: { get: function() { return store.getState().activeSessionId; }, enumerable: true },
1308
+ myUserId: { get: function() { return store.getState().myUserId; }, enumerable: true },
1320
1309
  });
1321
1310
  initDm(_dmCtx);
1322
1311
 
1323
- // --- Messages module ---
1324
- var _msgCtx = {
1325
- // DOM refs
1326
- messagesEl: messagesEl,
1327
- headerTitleEl: headerTitleEl,
1328
- inputEl: inputEl,
1329
- connectOverlay: connectOverlay,
1330
- $: $,
1331
- // Functions - sidebar/session
1332
- renderMateSessionList: renderMateSessionList,
1333
- refreshMobileChatSheet: refreshMobileChatSheet,
1334
- handleMateSearchResults: handleMateSearchResults,
1335
- renderKnowledgeList: renderKnowledgeList,
1336
- handleKnowledgeContent: handleKnowledgeContent,
1337
- renderMemoryList: renderMemoryList,
1338
- updateMateSidebarProfile: updateMateSidebarProfile,
1339
- renderSessionList: renderSessionList,
1340
- handlePaletteSessionSwitch: handlePaletteSessionSwitch,
1341
- updateSessionPresence: updateSessionPresence,
1342
- populateCliSessionList: populateCliSessionList,
1343
- handleSearchResults: handleSearchResults,
1344
- handleFindInSessionResults: handleFindInSessionResults,
1345
- blinkSessionDot: blinkSessionDot,
1346
- updateSessionBadge: updateSessionBadge,
1347
- updatePageTitle: updatePageTitle,
1348
- setPaletteVersion: setPaletteVersion,
1349
- hideHomeHub: hideHomeHub,
1350
- clearRemoteCursors: clearRemoteCursors,
1351
- resetClientState: resetClientState,
1352
- // Functions - rendering
1353
- scrollToBottom: scrollToBottom,
1354
- addToMessages: addToMessages,
1355
- addUserMessage: addUserMessage,
1356
- addSystemMessage: addSystemMessage,
1357
- renderMarkdown: renderMarkdown,
1358
- refreshIcons: refreshIcons,
1359
- iconHtml: iconHtml,
1360
- showImageModal: showImageModal,
1361
- showToast: showToast,
1362
- autoResize: autoResize,
1363
- // Functions - tools/thinking
1364
- startThinking: startThinking,
1365
- appendThinking: appendThinking,
1366
- stopThinking: stopThinking,
1367
- resetThinkingGroup: resetThinkingGroup,
1368
- removeMatePreThinking: removeMatePreThinking,
1369
- appendDelta: appendDelta,
1370
- createToolItem: createToolItem,
1371
- updateToolExecuting: updateToolExecuting,
1372
- updateToolResult: updateToolResult,
1373
- markAllToolsDone: markAllToolsDone,
1374
- closeToolGroup: closeToolGroup,
1375
- removeToolFromGroup: removeToolFromGroup,
1376
- resetToolState: resetToolState,
1377
- getTools: getTools,
1378
- getPlanContent: getPlanContent,
1379
- setPlanContent: setPlanContent,
1380
- renderPlanBanner: renderPlanBanner,
1381
- renderPlanCard: renderPlanCard,
1382
- getTodoTools: getTodoTools,
1383
- handleTodoWrite: handleTodoWrite,
1384
- handleTaskCreate: handleTaskCreate,
1385
- handleTaskUpdate: handleTaskUpdate,
1386
- isPlanFilePath: isPlanFilePath,
1387
- enableMainInput: enableMainInput,
1388
- addTurnMeta: addTurnMeta,
1389
- // Functions - subagents
1390
- updateSubagentActivity: updateSubagentActivity,
1391
- addSubagentToolEntry: addSubagentToolEntry,
1392
- markSubagentDone: markSubagentDone,
1393
- initSubagentStop: initSubagentStop,
1394
- updateSubagentProgress: updateSubagentProgress,
1395
- // Functions - permissions/elicitation
1396
- renderAskUserQuestion: renderAskUserQuestion,
1397
- markAskUserAnswered: markAskUserAnswered,
1398
- renderPermissionRequest: renderPermissionRequest,
1399
- markPermissionCancelled: markPermissionCancelled,
1400
- markPermissionResolved: markPermissionResolved,
1401
- renderElicitationRequest: renderElicitationRequest,
1402
- markElicitationResolved: markElicitationResolved,
1403
- // Functions - status
1404
- setStatus: setStatus,
1405
- setActivity: setActivity,
1406
- setSendBtnMode: setSendBtnMode,
1407
- hasSendableContent: hasSendableContent,
1408
- startUrgentBlink: startUrgentBlink,
1409
- stopUrgentBlink: stopUrgentBlink,
1410
- finalizeAssistantBlock: finalizeAssistantBlock,
1411
- // Functions - usage/context
1412
- accumulateUsage: accumulateUsage,
1413
- accumulateContext: accumulateContext,
1414
- updateContextPanel: updateContextPanel,
1415
- updateUsagePanel: updateUsagePanel,
1416
- renderCtxPopover: renderCtxPopover,
1417
- // Functions - notifications
1418
- showDoneNotification: showDoneNotification,
1419
- playDoneSound: playDoneSound,
1420
- isNotifAlertEnabled: isNotifAlertEnabled,
1421
- isNotifSoundEnabled: isNotifSoundEnabled,
1422
- // Functions - filesystem
1423
- handleFsList: handleFsList,
1424
- handleFsRead: handleFsRead,
1425
- isProjectSettingsOpen: isProjectSettingsOpen,
1426
- handleInstructionsRead: handleInstructionsRead,
1427
- handleInstructionsWrite: handleInstructionsWrite,
1428
- handleProjectEnv: handleProjectEnv,
1429
- handleProjectEnvSaved: handleProjectEnvSaved,
1430
- handleGlobalClaudeMdRead: handleGlobalClaudeMdRead,
1431
- handleGlobalClaudeMdWrite: handleGlobalClaudeMdWrite,
1432
- handleSharedEnv: handleSharedEnv,
1433
- handleProjectSharedEnv: handleProjectSharedEnv,
1434
- handleSharedEnvSaved: handleSharedEnvSaved,
1435
- handleProjectSharedEnvSaved: handleProjectSharedEnvSaved,
1436
- handleFileChanged: handleFileChanged,
1437
- handleDirChanged: handleDirChanged,
1438
- handleFileHistory: handleFileHistory,
1439
- handleGitDiff: handleGitDiff,
1440
- handleFileAt: handleFileAt,
1441
- refreshIfOpen: refreshIfOpen,
1442
- getPendingNavigate: getPendingNavigate,
1443
- // Functions - terminals
1444
- handleTermList: handleTermList,
1445
- updateTerminalList: updateTerminalList,
1446
- handleContextSourcesState: handleContextSourcesState,
1447
- sendExtensionCommand: sendExtensionCommand,
1448
- handleTermCreated: handleTermCreated,
1449
- sendTerminalCommand: sendTerminalCommand,
1450
- handleTermOutput: handleTermOutput,
1451
- handleTermResized: handleTermResized,
1452
- handleTermExited: handleTermExited,
1453
- handleTermClosed: handleTermClosed,
1454
- // Functions - notes
1455
- handleNotesList: handleNotesList,
1456
- handleNoteCreated: handleNoteCreated,
1457
- handleNoteUpdated: handleNoteUpdated,
1458
- handleNoteDeleted: handleNoteDeleted,
1459
- // Functions - projects
1460
- updateProjectList: updateProjectList,
1461
- handleBrowseDirResult: handleBrowseDirResult,
1462
- handleAddProjectResult: handleAddProjectResult,
1463
- handleCloneProgress: handleCloneProgress,
1464
- handleRemoveProjectResult: handleRemoveProjectResult,
1465
- handleRemoveProjectCheckResult: handleRemoveProjectCheckResult,
1466
- handleProjectOwnerChanged: handleProjectOwnerChanged,
1467
- // Functions - settings/config
1468
- updateConfigChip: updateConfigChip,
1469
- getModelEffortLevels: getModelEffortLevels,
1470
- updateSettingsModels: updateSettingsModels,
1471
- updateSettingsStats: updateSettingsStats,
1472
- updateStatusPanel: updateStatusPanel,
1473
- updateDaemonConfig: updateDaemonConfig,
1474
- handleSetPinResult: handleSetPinResult,
1475
- handleKeepAwakeChanged: handleKeepAwakeChanged,
1476
- handleAutoContinueChanged: handleAutoContinueChanged,
1477
- handleRestartResult: handleRestartResult,
1478
- handleShutdownResult: handleShutdownResult,
1479
- showUpdateAvailable: showUpdateAvailable,
1480
- checkAdminAccess: checkAdminAccess,
1481
- renderSidebarPresence: renderSidebarPresence,
1482
- // Functions - skills
1483
- handleSkillInstalled: handleSkillInstalled,
1484
- handleSkillInstallWs: handleSkillInstallWs,
1485
- handleSkillUninstalled: handleSkillUninstalled,
1486
- // Functions - DM
1487
- enterDmMode: enterDmMode,
1488
- exitDmMode: exitDmMode,
1489
- openDm: openDm,
1490
- appendDmMessage: appendDmMessage,
1491
- showDmTypingIndicator: showDmTypingIndicator,
1492
- buildMateInterviewPrompt: buildMateInterviewPrompt,
1493
- handleMateCreatedInApp: handleMateCreatedInApp,
1494
- updateMateIconStatus: updateMateIconStatus,
1495
- updateDmBadge: updateDmBadge,
1496
- renderUserStrip: renderUserStrip,
1497
- mateAvatarUrl: mateAvatarUrl,
1498
- // Functions - mention
1499
- handleMentionStart: handleMentionStart,
1500
- handleMentionActivity: handleMentionActivity,
1501
- handleMentionStream: handleMentionStream,
1502
- handleMentionDone: handleMentionDone,
1503
- handleMentionError: handleMentionError,
1504
- renderMentionUser: renderMentionUser,
1505
- renderMentionResponse: renderMentionResponse,
1506
- // Functions - debate
1507
- showDebateSticky: showDebateSticky,
1508
- handleDebatePreparing: handleDebatePreparing,
1509
- handleDebateBriefReady: handleDebateBriefReady,
1510
- renderDebateBriefReady: renderDebateBriefReady,
1511
- handleDebateStarted: handleDebateStarted,
1512
- renderDebateStarted: renderDebateStarted,
1513
- handleDebateTurn: handleDebateTurn,
1514
- updateDebateRound: updateDebateRound,
1515
- handleDebateActivity: handleDebateActivity,
1516
- handleDebateStream: handleDebateStream,
1517
- handleDebateTurnDone: handleDebateTurnDone,
1518
- handleDebateCommentQueued: handleDebateCommentQueued,
1519
- handleDebateCommentInjected: handleDebateCommentInjected,
1520
- renderDebateCommentInjected: renderDebateCommentInjected,
1521
- showDebateConcludeConfirm: showDebateConcludeConfirm,
1522
- showDebateUserFloor: showDebateUserFloor,
1523
- renderDebateUserFloorDone: renderDebateUserFloorDone,
1524
- renderDebateUserResume: renderDebateUserResume,
1525
- handleDebateResumed: handleDebateResumed,
1526
- handleDebateEnded: handleDebateEnded,
1527
- renderDebateEnded: renderDebateEnded,
1528
- handleDebateError: handleDebateError,
1529
- isDebateActive: isDebateActive,
1530
- exitDebateFloorMode: exitDebateFloorMode,
1531
- exitDebateConcludeMode: exitDebateConcludeMode,
1532
- exitDebateEndedMode: exitDebateEndedMode,
1533
- renderMcpDebateProposal: renderMcpDebateProposal,
1534
- // Functions - loop/ralph
1535
- updateLoopButton: updateLoopButton,
1536
- showLoopBanner: showLoopBanner,
1537
- updateLoopBanner: updateLoopBanner,
1538
- updateRalphBars: updateRalphBars,
1539
- updateLoopInputVisibility: updateLoopInputVisibility,
1540
- showRalphApprovalBar: showRalphApprovalBar,
1541
- updateRalphApprovalStatus: updateRalphApprovalStatus,
1542
- openRalphPreviewModal: openRalphPreviewModal,
1543
- showExecModal: showExecModal,
1544
- closeExecModal: closeExecModal,
1545
- updateExecModalStatus: updateExecModalStatus,
1546
- getExecModalShown: function () { return getExecModalShown(); },
1547
- setWizardData: function (v) { setWizardData(v); },
1548
- enterCraftingMode: enterCraftingMode,
1549
- exitCraftingMode: exitCraftingMode,
1550
- isSchedulerOpen: isSchedulerOpen,
1551
- handleLoopRegistryUpdated: handleLoopRegistryUpdated,
1552
- handleScheduleRunStarted: handleScheduleRunStarted,
1553
- handleScheduleRunFinished: handleScheduleRunFinished,
1554
- handleLoopScheduled: handleLoopScheduled,
1555
- handleHubSchedules: handleHubSchedules,
1556
- handleLoopRegistryFiles: handleLoopRegistryFiles,
1557
- // Functions - notifications
1558
- handleNotificationsState: handleNotificationsState,
1559
- handleNotificationCreated: handleNotificationCreated,
1560
- handleNotificationDismissed: handleNotificationDismissed,
1561
- handleNotificationDismissedAll: handleNotificationDismissedAll,
1562
- // Functions - input/misc
1563
- handleInputSync: handleInputSync,
1564
- handleRateLimitEvent: handleRateLimitEvent,
1565
- updateRateLimitUsage: updateRateLimitUsage,
1566
- addScheduledMessageBubble: addScheduledMessageBubble,
1567
- removeScheduledMessageBubble: removeScheduledMessageBubble,
1568
- setScheduleBtnDisabled: setScheduleBtnDisabled,
1569
- showSuggestionChips: showSuggestionChips,
1570
- handleFastModeState: handleFastModeState,
1571
- addConflictMessage: addConflictMessage,
1572
- addContextOverflowMessage: addContextOverflowMessage,
1573
- addAuthRequiredMessage: addAuthRequiredMessage,
1574
- // Functions - rewind
1575
- showRewindModal: showRewindModal,
1576
- onRewindComplete: onRewindComplete,
1577
- setRewindMode: setRewindMode,
1578
- onRewindError: onRewindError,
1579
- clearPendingRewindUuid: clearPendingRewindUuid,
1580
- addRewindButton: addRewindButton,
1581
- // Functions - cursors
1582
- handleRemoteCursorMove: handleRemoteCursorMove,
1583
- handleRemoteCursorLeave: handleRemoteCursorLeave,
1584
- handleRemoteSelection: handleRemoteSelection,
1585
- // Functions - history
1586
- updateHistorySentinel: updateHistorySentinel,
1587
- prependOlderHistory: prependOlderHistory,
1588
- // Functions - builtinCommands
1589
- builtinCommands: builtinCommands,
1590
- };
1591
- // Add mutable state with live get/set accessors
1592
- var _msgStateProps = {
1593
- currentMsgTs: function() { return getCurrentMsgTs(); }, _currentMsgTs: function(v) { setCurrentMsgTs(v); },
1594
- dmMode: function() { return dmMode; }, _dmMode: function(v) { dmMode = v; },
1595
- dmTargetUser: function() { return dmTargetUser; },
1596
- ws: function() { return ws; },
1597
- historyFrom: function() { return historyFrom; }, _historyFrom: function(v) { historyFrom = v; },
1598
- historyTotal: function() { return historyTotal; }, _historyTotal: function(v) { historyTotal = v; },
1599
- replayingHistory: function() { return getReplayingHistory(); }, _replayingHistory: function(v) { setReplayingHistory(v); },
1600
- richContextUsage: function() { return getRichContextUsage(); }, _richContextUsage: function(v) { setRichContextUsage(v); },
1601
- projectName: function() { return projectName; }, _projectName: function(v) { projectName = v; },
1602
- currentSlug: function() { return currentSlug; }, _currentSlug: function(v) { currentSlug = v; },
1603
- currentProjectOwnerId: function() { return currentProjectOwnerId; }, _currentProjectOwnerId: function(v) { currentProjectOwnerId = v; },
1604
- isOsUsers: function() { return isOsUsers; }, _isOsUsers: function(v) { isOsUsers = v; },
1605
- skipPermsEnabled: function() { return skipPermsEnabled; }, _skipPermsEnabled: function(v) { skipPermsEnabled = v; },
1606
- currentModel: function() { return getCurrentModel(); }, _currentModel: function(v) { setCurrentModel(v); },
1607
- currentModels: function() { return getCurrentModels(); }, _currentModels: function(v) { setCurrentModels(v); },
1608
- currentMode: function() { return getCurrentMode(); }, _currentMode: function(v) { setCurrentMode(v); },
1609
- currentEffort: function() { return getCurrentEffort(); }, _currentEffort: function(v) { setCurrentEffort(v); },
1610
- currentBetas: function() { return getCurrentBetas(); }, _currentBetas: function(v) { setCurrentBetas(v); },
1611
- currentThinking: function() { return getCurrentThinking(); }, _currentThinking: function(v) { setCurrentThinking(v); },
1612
- currentThinkingBudget: function() { return getCurrentThinkingBudget(); }, _currentThinkingBudget: function(v) { setCurrentThinkingBudget(v); },
1613
- slashCommands: function() { return slashCommands; }, _slashCommands: function(v) { slashCommands = v; },
1614
- returningFromMateDm: function() { return returningFromMateDm; }, _returningFromMateDm: function(v) { returningFromMateDm = v; },
1615
- processing: function() { return processing; }, _processing: function(v) { processing = v; },
1616
- loopActive: function() { return getLoopActive(); }, _loopActive: function(v) { setLoopActive(v); },
1617
- loopAvailable: function() { return getLoopAvailable(); }, _loopAvailable: function(v) { setLoopAvailable(v); },
1618
- loopIteration: function() { return getLoopIteration(); }, _loopIteration: function(v) { setLoopIteration(v); },
1619
- loopMaxIterations: function() { return getLoopMaxIterations(); }, _loopMaxIterations: function(v) { setLoopMaxIterations(v); },
1620
- loopBannerName: function() { return getLoopBannerName(); }, _loopBannerName: function(v) { setLoopBannerName(v); },
1621
- ralphPhase: function() { return getRalphPhase(); }, _ralphPhase: function(v) { setRalphPhase(v); },
1622
- ralphCraftingSessionId: function() { return getRalphCraftingSessionId(); }, _ralphCraftingSessionId: function(v) { setRalphCraftingSessionId(v); },
1623
- ralphCraftingSource: function() { return getRalphCraftingSource(); }, _ralphCraftingSource: function(v) { setRalphCraftingSource(v); },
1624
- ralphFilesReady: function() { return getRalphFilesReady(); }, _ralphFilesReady: function(v) { setRalphFilesReady(v); },
1625
- ralphPreviewContent: function() { return getRalphPreviewContent(); }, _ralphPreviewContent: function(v) { setRalphPreviewContent(v); },
1626
- pendingMateInterview: function() { return pendingMateInterview; }, _pendingMateInterview: function(v) { pendingMateInterview = v; },
1627
- pendingTermCommand: function() { return pendingTermCommand; }, _pendingTermCommand: function(v) { pendingTermCommand = v; },
1628
- activeSessionId: function() { return activeSessionId; }, _activeSessionId: function(v) { activeSessionId = v; },
1629
- cliSessionId: function() { return cliSessionId; }, _cliSessionId: function(v) { cliSessionId = v; },
1630
- isHeadlessMode: function() { return isHeadlessMode; }, _isHeadlessMode: function(v) { isHeadlessMode = v; },
1631
- cachedMatesList: function() { return cachedMatesList; }, _cachedMatesList: function(v) { cachedMatesList = v; },
1632
- cachedDmFavorites: function() { return cachedDmFavorites; }, _cachedDmFavorites: function(v) { cachedDmFavorites = v; },
1633
- cachedAvailableBuiltins: function() { return cachedAvailableBuiltins; }, _cachedAvailableBuiltins: function(v) { cachedAvailableBuiltins = v; },
1634
- // Read-only mutable state (processMessage reads but doesn't reassign)
1635
- currentMsgEl: function() { return getCurrentMsgEl(); },
1636
- currentFullText: function() { return getCurrentFullText(); },
1637
- debateFloorMode: function() { return getDebateFloorMode(); },
1638
- debateConcludeMode: function() { return getDebateConcludeMode(); },
1639
- debateEndedMode: function() { return getDebateEndedMode(); },
1640
- ctxPopoverVisible: function() { return getCtxPopoverVisible(); },
1641
- headerContextEl: function() { return _panGetHeaderContextEl(); },
1642
- myUserId: function() { return myUserId; },
1643
- mateProjectSlug: function() { return mateProjectSlug; },
1644
- dmKey: function() { return dmKey; },
1645
- isMultiUserMode: function() { return isMultiUserMode; },
1646
- sessionDrafts: function() { return sessionDrafts; },
1647
- messageUuidMap: function() { return messageUuidMap; },
1648
- knownInstalledSkills: function() { return getKnownInstalledSkills(); },
1649
- dmUnread: function() { return dmUnread; },
1650
- dmRemovedUsers: function() { return dmRemovedUsers; },
1651
- cachedAllUsers: function() { return cachedAllUsers; },
1652
- cachedOnlineIds: function() { return cachedOnlineIds; },
1653
- cachedDmConversations: function() { return cachedDmConversations; },
1654
- matePreThinkingEl: function() { return getMatePreThinkingEl(); },
1655
- };
1656
- // Wire up defineProperty for each state var
1657
- Object.keys(_msgStateProps).forEach(function(key) {
1658
- if (key.charAt(0) === "_") return; // skip setter helpers
1659
- var getter = _msgStateProps[key];
1660
- var setter = _msgStateProps["_" + key];
1661
- var desc = { get: getter, enumerable: true };
1662
- if (setter) desc.set = setter;
1663
- Object.defineProperty(_msgCtx, key, desc);
1664
- });
1665
- initMessages(_msgCtx);
1312
+ // --- Messages module (uses direct imports, no ctx injection needed) ---
1666
1313
 
1667
1314
  // --- Connection module ---
1668
1315
  initConnection({
1669
1316
  getWs: function () { return ws; },
1670
- setWs: function (v) { ws = v; },
1671
- isConnected: function () { return connected; },
1672
- setConnected: function (v) { connected = v; },
1673
- setProcessing: function (v) { processing = v; },
1317
+ setWs: function (v) { ws = v; _setWsRef(v); },
1318
+ isConnected: function () { return store.getState().connected; },
1319
+ setConnected: function (v) { store.setState({ connected: v }); },
1320
+ setProcessing: function (v) { store.setState({ processing: v }); },
1674
1321
  getWsPath: function () { return wsPath; },
1675
1322
  getStatusDot: getStatusDot,
1676
1323
  sendBtn: sendBtn,
@@ -1704,7 +1351,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
1704
1351
  } catch(e) {}
1705
1352
 
1706
1353
  // If connecting to a mate project, request knowledge list for badge
1707
- if (mateProjectSlug) {
1354
+ if (store.getState().mateProjectSlug) {
1708
1355
  try { ws.send(JSON.stringify({ type: "knowledge_list" })); } catch(e) {}
1709
1356
  }
1710
1357
 
@@ -1713,9 +1360,9 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
1713
1360
  // Fallback: if server doesn't restore DM within 2s, try localStorage
1714
1361
  var savedDm = null;
1715
1362
  try { savedDm = localStorage.getItem("clay-active-dm"); } catch (e) {}
1716
- if (savedDm && !dmMode && !mateProjectSlug) {
1363
+ if (savedDm && !store.getState().dmMode && !store.getState().mateProjectSlug) {
1717
1364
  var dmFallbackTimer = setTimeout(function () {
1718
- if (!dmMode && savedDm) {
1365
+ if (!store.getState().dmMode && savedDm) {
1719
1366
  console.log("[dm-restore] Server did not restore DM, using localStorage fallback:", savedDm);
1720
1367
  openDm(savedDm);
1721
1368
  }
@@ -1735,10 +1382,10 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
1735
1382
  setTimeout(function () { ws.removeEventListener("message", checkRestore); }, 3000);
1736
1383
  }
1737
1384
  // Safety: clear returningFromMateDm after initial messages settle
1738
- if (returningFromMateDm) {
1385
+ if (store.getState().returningFromMateDm) {
1739
1386
  setTimeout(function () {
1740
- if (returningFromMateDm) {
1741
- returningFromMateDm = false;
1387
+ if (store.getState().returningFromMateDm) {
1388
+ store.setState({ returningFromMateDm: false });
1742
1389
  }
1743
1390
  }, 2000);
1744
1391
  }
@@ -1748,7 +1395,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
1748
1395
  // --- Init ---
1749
1396
  lucide.createIcons();
1750
1397
  connect();
1751
- if (!currentSlug) {
1398
+ if (!store.getState().currentSlug) {
1752
1399
  showHomeHub();
1753
1400
  } else if (location.hash === "#scheduler") {
1754
1401
  // Restore scheduler view after refresh