hammoc 1.7.1 → 1.8.0
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/README.md +8 -4
- package/package.json +1 -1
- package/packages/client/dist/assets/{agentExampleHighlight-Du5I7v6o.js → agentExampleHighlight-B2IJxYzN.js} +1 -1
- package/packages/client/dist/assets/{commandTokenHighlight-Dfo51Aof.js → commandTokenHighlight-BdGXkDR5.js} +1 -1
- package/packages/client/dist/assets/{index-4l4YwxEs.js → index-BFWGN51V.js} +1 -1
- package/packages/client/dist/assets/index-BX7y_Qt3.css +32 -0
- package/packages/client/dist/assets/{index-CqAHxPRw.js → index-lmx-m-iP.js} +587 -499
- package/packages/client/dist/assets/{snippetTokenHighlight-26DWljQA.js → snippetTokenHighlight-B9bH9Npx.js} +1 -1
- package/packages/client/dist/index.html +2 -2
- package/packages/client/dist/sw.js +1 -1
- package/packages/server/dist/app.d.ts.map +1 -1
- package/packages/server/dist/app.js +25 -1
- package/packages/server/dist/app.js.map +1 -1
- package/packages/server/dist/config/index.d.ts +10 -0
- package/packages/server/dist/config/index.d.ts.map +1 -1
- package/packages/server/dist/config/index.js +10 -0
- package/packages/server/dist/config/index.js.map +1 -1
- package/packages/server/dist/controllers/accountController.d.ts +19 -0
- package/packages/server/dist/controllers/accountController.d.ts.map +1 -0
- package/packages/server/dist/controllers/accountController.js +92 -0
- package/packages/server/dist/controllers/accountController.js.map +1 -0
- package/packages/server/dist/controllers/gitController.d.ts.map +1 -1
- package/packages/server/dist/controllers/gitController.js +37 -0
- package/packages/server/dist/controllers/gitController.js.map +1 -1
- package/packages/server/dist/controllers/projectController.d.ts +1 -1
- package/packages/server/dist/controllers/projectController.d.ts.map +1 -1
- package/packages/server/dist/controllers/projectController.js +20 -4
- package/packages/server/dist/controllers/projectController.js.map +1 -1
- package/packages/server/dist/controllers/serverController.d.ts.map +1 -1
- package/packages/server/dist/controllers/serverController.js +8 -1
- package/packages/server/dist/controllers/serverController.js.map +1 -1
- package/packages/server/dist/controllers/sessionController.d.ts.map +1 -1
- package/packages/server/dist/controllers/sessionController.js +3 -1
- package/packages/server/dist/controllers/sessionController.js.map +1 -1
- package/packages/server/dist/handlers/websocket.d.ts +4 -0
- package/packages/server/dist/handlers/websocket.d.ts.map +1 -1
- package/packages/server/dist/handlers/websocket.js +146 -8
- package/packages/server/dist/handlers/websocket.js.map +1 -1
- package/packages/server/dist/index.js +8 -0
- package/packages/server/dist/index.js.map +1 -1
- package/packages/server/dist/locales/en/server.json +2 -0
- package/packages/server/dist/locales/es/server.json +2 -0
- package/packages/server/dist/locales/ja/server.json +2 -0
- package/packages/server/dist/locales/ko/server.json +2 -0
- package/packages/server/dist/locales/pt/server.json +2 -0
- package/packages/server/dist/locales/zh-CN/server.json +2 -0
- package/packages/server/dist/middleware/session.d.ts.map +1 -1
- package/packages/server/dist/middleware/session.js +7 -5
- package/packages/server/dist/middleware/session.js.map +1 -1
- package/packages/server/dist/routes/accounts.d.ts +13 -0
- package/packages/server/dist/routes/accounts.d.ts.map +1 -0
- package/packages/server/dist/routes/accounts.js +18 -0
- package/packages/server/dist/routes/accounts.js.map +1 -0
- package/packages/server/dist/routes/config.d.ts +3 -0
- package/packages/server/dist/routes/config.d.ts.map +1 -0
- package/packages/server/dist/routes/config.js +59 -0
- package/packages/server/dist/routes/config.js.map +1 -0
- package/packages/server/dist/routes/preferences.d.ts.map +1 -1
- package/packages/server/dist/routes/preferences.js +22 -4
- package/packages/server/dist/routes/preferences.js.map +1 -1
- package/packages/server/dist/services/accountInfoService.js +6 -6
- package/packages/server/dist/services/accountInfoService.js.map +1 -1
- package/packages/server/dist/services/accountStorageService.d.ts +119 -0
- package/packages/server/dist/services/accountStorageService.d.ts.map +1 -0
- package/packages/server/dist/services/accountStorageService.js +285 -0
- package/packages/server/dist/services/accountStorageService.js.map +1 -0
- package/packages/server/dist/services/chatService.d.ts.map +1 -1
- package/packages/server/dist/services/chatService.js +4 -8
- package/packages/server/dist/services/chatService.js.map +1 -1
- package/packages/server/dist/services/claudeLoginService.d.ts +124 -0
- package/packages/server/dist/services/claudeLoginService.d.ts.map +1 -0
- package/packages/server/dist/services/claudeLoginService.js +417 -0
- package/packages/server/dist/services/claudeLoginService.js.map +1 -0
- package/packages/server/dist/services/cliChatEngine.d.ts.map +1 -1
- package/packages/server/dist/services/cliChatEngine.js +85 -33
- package/packages/server/dist/services/cliChatEngine.js.map +1 -1
- package/packages/server/dist/services/cliGridCards.d.ts +30 -10
- package/packages/server/dist/services/cliGridCards.d.ts.map +1 -1
- package/packages/server/dist/services/cliGridCards.js +80 -34
- package/packages/server/dist/services/cliGridCards.js.map +1 -1
- package/packages/server/dist/services/cliModalDetect.d.ts +15 -7
- package/packages/server/dist/services/cliModalDetect.d.ts.map +1 -1
- package/packages/server/dist/services/cliModalDetect.js +16 -12
- package/packages/server/dist/services/cliModalDetect.js.map +1 -1
- package/packages/server/dist/services/cliScreenModel.d.ts +3 -2
- package/packages/server/dist/services/cliScreenModel.d.ts.map +1 -1
- package/packages/server/dist/services/cliScreenModel.js +2 -0
- package/packages/server/dist/services/cliScreenModel.js.map +1 -1
- package/packages/server/dist/services/cliService.d.ts.map +1 -1
- package/packages/server/dist/services/cliService.js +2 -7
- package/packages/server/dist/services/cliService.js.map +1 -1
- package/packages/server/dist/services/cliSessionPool.d.ts +13 -1
- package/packages/server/dist/services/cliSessionPool.d.ts.map +1 -1
- package/packages/server/dist/services/cliSessionPool.js +14 -4
- package/packages/server/dist/services/cliSessionPool.js.map +1 -1
- package/packages/server/dist/services/dashboardService.d.ts.map +1 -1
- package/packages/server/dist/services/dashboardService.js +6 -1
- package/packages/server/dist/services/dashboardService.js.map +1 -1
- package/packages/server/dist/services/gitService.d.ts +2 -0
- package/packages/server/dist/services/gitService.d.ts.map +1 -1
- package/packages/server/dist/services/gitService.js +41 -3
- package/packages/server/dist/services/gitService.js.map +1 -1
- package/packages/server/dist/services/preferencesService.d.ts +1 -0
- package/packages/server/dist/services/preferencesService.d.ts.map +1 -1
- package/packages/server/dist/services/preferencesService.js +25 -2
- package/packages/server/dist/services/preferencesService.js.map +1 -1
- package/packages/server/dist/services/queueService.d.ts +1 -0
- package/packages/server/dist/services/queueService.d.ts.map +1 -1
- package/packages/server/dist/services/queueService.js +14 -3
- package/packages/server/dist/services/queueService.js.map +1 -1
- package/packages/server/dist/services/rateLimitProbeService.d.ts +7 -0
- package/packages/server/dist/services/rateLimitProbeService.d.ts.map +1 -1
- package/packages/server/dist/services/rateLimitProbeService.js +10 -0
- package/packages/server/dist/services/rateLimitProbeService.js.map +1 -1
- package/packages/server/dist/services/workspaceContext.d.ts +31 -4
- package/packages/server/dist/services/workspaceContext.d.ts.map +1 -1
- package/packages/server/dist/services/workspaceContext.js +110 -10
- package/packages/server/dist/services/workspaceContext.js.map +1 -1
- package/packages/server/dist/snippets/promote-to-story +86 -9
- package/packages/server/dist/utils/cliDebugLog.d.ts +6 -5
- package/packages/server/dist/utils/cliDebugLog.d.ts.map +1 -1
- package/packages/server/dist/utils/cliDebugLog.js +11 -8
- package/packages/server/dist/utils/cliDebugLog.js.map +1 -1
- package/packages/server/dist/utils/logger.d.ts +7 -0
- package/packages/server/dist/utils/logger.d.ts.map +1 -1
- package/packages/server/dist/utils/logger.js +13 -1
- package/packages/server/dist/utils/logger.js.map +1 -1
- package/packages/server/resources/bmad-method/4.44.3/LICENSE +30 -0
- package/packages/server/resources/manual/01-getting-started.md +11 -5
- package/packages/server/resources/manual/02-chat.md +2 -2
- package/packages/server/resources/manual/03-sessions.md +2 -0
- package/packages/server/resources/manual/04-slash-commands-favorites.md +1 -0
- package/packages/server/resources/manual/05-projects.md +2 -2
- package/packages/server/resources/manual/07-git.md +23 -2
- package/packages/server/resources/manual/08-terminal.md +24 -1
- package/packages/server/resources/manual/11-bmad-method-integration.md +1 -0
- package/packages/server/resources/manual/13-settings.md +52 -20
- package/packages/server/resources/manual/16-troubleshooting.md +4 -7
- package/packages/shared/dist/index.d.ts +2 -1
- package/packages/shared/dist/index.d.ts.map +1 -1
- package/packages/shared/dist/index.js +2 -0
- package/packages/shared/dist/index.js.map +1 -1
- package/packages/shared/dist/types/accounts.d.ts +104 -0
- package/packages/shared/dist/types/accounts.d.ts.map +1 -0
- package/packages/shared/dist/types/accounts.js +14 -0
- package/packages/shared/dist/types/accounts.js.map +1 -0
- package/packages/shared/dist/types/dashboard.d.ts +1 -0
- package/packages/shared/dist/types/dashboard.d.ts.map +1 -1
- package/packages/shared/dist/types/git.d.ts +12 -0
- package/packages/shared/dist/types/git.d.ts.map +1 -1
- package/packages/shared/dist/types/git.js +10 -0
- package/packages/shared/dist/types/git.js.map +1 -1
- package/packages/shared/dist/types/preferences.d.ts +40 -0
- package/packages/shared/dist/types/preferences.d.ts.map +1 -1
- package/packages/shared/dist/types/preferences.js.map +1 -1
- package/packages/shared/dist/types/sdk.d.ts +5 -1
- package/packages/shared/dist/types/sdk.d.ts.map +1 -1
- package/packages/shared/dist/types/sdk.js.map +1 -1
- package/packages/shared/dist/types/session.d.ts +1 -0
- package/packages/shared/dist/types/session.d.ts.map +1 -1
- package/packages/shared/dist/types/session.js.map +1 -1
- package/packages/shared/dist/types/websocket.d.ts +28 -1
- package/packages/shared/dist/types/websocket.d.ts.map +1 -1
- package/packages/client/dist/assets/index-CVy582lU.css +0 -32
- package/packages/server/dist/snippets/promote-issue +0 -9
|
@@ -39,6 +39,9 @@ import { buildRawMessageTree, getActiveRawBranch, getDefaultRawBranchSelections,
|
|
|
39
39
|
import { sessionBufferManager } from '../services/sessionBufferManager.js';
|
|
40
40
|
import { imageStorageService } from '../services/imageStorageService.js';
|
|
41
41
|
import { isSnippetRef, resolveSnippet, listSnippets, SnippetError } from '../utils/snippetResolver.js';
|
|
42
|
+
import { ClaudeLoginSession, deleteCredentials } from '../services/claudeLoginService.js';
|
|
43
|
+
import { accountInfoService } from '../services/accountInfoService.js';
|
|
44
|
+
import { accountStorageService } from '../services/accountStorageService.js';
|
|
42
45
|
const log = createLogger('websocket');
|
|
43
46
|
// Alias for concise usage in guards
|
|
44
47
|
const queueInstances = getQueueInstances;
|
|
@@ -46,6 +49,8 @@ const queueInstances = getQueueInstances;
|
|
|
46
49
|
const warnedMissing1M = new Set();
|
|
47
50
|
// Socket-to-terminal mapping: socket.id → Set of terminalIds (Story 17.1)
|
|
48
51
|
const socketTerminals = new Map();
|
|
52
|
+
// Story BS-7: one in-flight Claude Code login session per socket (disposable PTY).
|
|
53
|
+
const socketLoginSessions = new Map();
|
|
49
54
|
// Story 20.1: Session-to-project mapping for dashboard triggers
|
|
50
55
|
const sessionProjectMap = new Map();
|
|
51
56
|
// Story 20.1: Per-project debounced dashboard status change broadcaster
|
|
@@ -456,6 +461,38 @@ export function isSessionStreaming(sessionId) {
|
|
|
456
461
|
const stream = activeStreams.get(sessionId);
|
|
457
462
|
return !!stream && stream.status === 'running';
|
|
458
463
|
}
|
|
464
|
+
/** Check if a session has any pending AskUserQuestion interactions */
|
|
465
|
+
export function sessionHasPendingQuestion(sessionId) {
|
|
466
|
+
const stream = activeStreams.get(sessionId);
|
|
467
|
+
if (!stream)
|
|
468
|
+
return false;
|
|
469
|
+
for (const p of stream.pendingPermissions.values()) {
|
|
470
|
+
if (p.interactionType === 'question')
|
|
471
|
+
return true;
|
|
472
|
+
}
|
|
473
|
+
return false;
|
|
474
|
+
}
|
|
475
|
+
/** Get pending AskUserQuestion counts grouped by project slug (in-memory, no I/O) */
|
|
476
|
+
export function getPendingQuestionCountsByProject() {
|
|
477
|
+
const counts = new Map();
|
|
478
|
+
for (const [sessionId, stream] of activeStreams.entries()) {
|
|
479
|
+
if (stream.status !== 'running')
|
|
480
|
+
continue;
|
|
481
|
+
let hasQuestion = false;
|
|
482
|
+
for (const p of stream.pendingPermissions.values()) {
|
|
483
|
+
if (p.interactionType === 'question') {
|
|
484
|
+
hasQuestion = true;
|
|
485
|
+
break;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
if (hasQuestion) {
|
|
489
|
+
const slug = sessionProjectMap.get(sessionId);
|
|
490
|
+
if (slug)
|
|
491
|
+
counts.set(slug, (counts.get(slug) ?? 0) + 1);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
return counts;
|
|
495
|
+
}
|
|
459
496
|
/** Get session IDs that have active socket connections for a given project */
|
|
460
497
|
export function getJoinedSessionIdsByProject(projectSlug) {
|
|
461
498
|
const sessionIds = new Set();
|
|
@@ -566,6 +603,15 @@ function cleanupStream(streamKey, expectedStream) {
|
|
|
566
603
|
// Only delete from activeStreams and clean up socket mappings if the stream
|
|
567
604
|
// hasn't been replaced. When replaced, the new stream owns those resources.
|
|
568
605
|
if (!replaced) {
|
|
606
|
+
// Clear pending question state before removing the stream
|
|
607
|
+
if (current) {
|
|
608
|
+
for (const p of current.pendingPermissions.values()) {
|
|
609
|
+
if (p.interactionType === 'question') {
|
|
610
|
+
emitQuestionChange(streamKey, false);
|
|
611
|
+
break;
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
}
|
|
569
615
|
activeStreams.delete(streamKey);
|
|
570
616
|
for (const [sockId, sessId] of socketToSession.entries()) {
|
|
571
617
|
if (sessId === streamKey)
|
|
@@ -719,6 +765,17 @@ function emitStreamChange(sessionId, active, projectSlug) {
|
|
|
719
765
|
}
|
|
720
766
|
}
|
|
721
767
|
}
|
|
768
|
+
/**
|
|
769
|
+
* Emit session:question-change when an AskUserQuestion becomes pending or is resolved.
|
|
770
|
+
* Scoped to the project room so only relevant session list viewers receive it.
|
|
771
|
+
*/
|
|
772
|
+
function emitQuestionChange(sessionId, hasPendingQuestion) {
|
|
773
|
+
const projectSlug = sessionProjectMap.get(sessionId);
|
|
774
|
+
if (projectSlug) {
|
|
775
|
+
io.to(`project:${projectSlug}`).emit('session:question-change', { sessionId, hasPendingQuestion, projectSlug });
|
|
776
|
+
triggerDashboardStatusChange(projectSlug);
|
|
777
|
+
}
|
|
778
|
+
}
|
|
722
779
|
/**
|
|
723
780
|
* Broadcast session:stream-change to project room (or all clients as fallback).
|
|
724
781
|
* Used by queue service to signal stream start/end.
|
|
@@ -787,11 +844,13 @@ export async function initializeWebSocket(httpServer) {
|
|
|
787
844
|
});
|
|
788
845
|
// Session middleware for WebSocket (Story 2.5 - Task 4)
|
|
789
846
|
const sessionMiddleware = await createSessionMiddleware();
|
|
790
|
-
// Parse session from cookie for Socket.io connections
|
|
847
|
+
// Parse session from cookie for Socket.io connections.
|
|
848
|
+
// cookie-session + on-headers expect a response-like object; a real
|
|
849
|
+
// ServerResponse would try to send headers over the upgraded WebSocket.
|
|
791
850
|
io.use((socket, next) => {
|
|
792
|
-
// Express middleware adapter for Socket.io
|
|
793
851
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
794
|
-
|
|
852
|
+
const res = { getHeader() { }, setHeader() { }, writeHead() { } };
|
|
853
|
+
sessionMiddleware(socket.request, res, next);
|
|
795
854
|
});
|
|
796
855
|
// Authentication middleware (Story 2.5 - Task 4)
|
|
797
856
|
io.use((socket, next) => {
|
|
@@ -1032,9 +1091,15 @@ export async function initializeWebSocket(httpServer) {
|
|
|
1032
1091
|
if (!sessionId)
|
|
1033
1092
|
return;
|
|
1034
1093
|
const stream = activeStreams.get(sessionId);
|
|
1035
|
-
if (stream
|
|
1036
|
-
|
|
1094
|
+
if (!stream)
|
|
1095
|
+
return;
|
|
1096
|
+
const pending = stream.pendingPermissions.get(data.requestId);
|
|
1097
|
+
if (pending) {
|
|
1098
|
+
const wasQuestion = pending.interactionType === 'question';
|
|
1099
|
+
pending.resolve({ approved: data.approved, response: data.response });
|
|
1037
1100
|
stream.pendingPermissions.delete(data.requestId);
|
|
1101
|
+
if (wasQuestion)
|
|
1102
|
+
emitQuestionChange(sessionId, sessionHasPendingQuestion(sessionId));
|
|
1038
1103
|
// Broadcast the actual resolution to all OTHER viewers so their
|
|
1039
1104
|
// tool/interactive cards can show the correct approve/deny state.
|
|
1040
1105
|
// Also buffer via createStreamEmit so reconnecting clients see the
|
|
@@ -2146,8 +2211,67 @@ export async function initializeWebSocket(httpServer) {
|
|
|
2146
2211
|
// Ignore close errors — session may already be gone
|
|
2147
2212
|
}
|
|
2148
2213
|
});
|
|
2214
|
+
// Story BS-7: Claude Code in-app login flow over a disposable PTY.
|
|
2215
|
+
// auth:start spawns the login session; the session drives boot → /login and reports each
|
|
2216
|
+
// phase back through these socket emits. One session per socket (a re-start disposes the prior).
|
|
2217
|
+
socket.on('auth:start', async () => {
|
|
2218
|
+
const prior = socketLoginSessions.get(socket.id);
|
|
2219
|
+
if (prior) {
|
|
2220
|
+
prior.dispose();
|
|
2221
|
+
socketLoginSessions.delete(socket.id);
|
|
2222
|
+
}
|
|
2223
|
+
// The login PTY uses the same binary-path override as chat (global preference).
|
|
2224
|
+
let cliBinaryPath;
|
|
2225
|
+
try {
|
|
2226
|
+
cliBinaryPath = (await preferencesService.readPreferences()).cliBinaryPath;
|
|
2227
|
+
}
|
|
2228
|
+
catch {
|
|
2229
|
+
cliBinaryPath = undefined;
|
|
2230
|
+
}
|
|
2231
|
+
const session = new ClaudeLoginSession({
|
|
2232
|
+
onMethodPrompt: () => socket.emit('auth:method-prompt'),
|
|
2233
|
+
onUrl: (url) => socket.emit('auth:url', { url }),
|
|
2234
|
+
onCodePrompt: () => socket.emit('auth:code-prompt'),
|
|
2235
|
+
onComplete: (account) => {
|
|
2236
|
+
socket.emit('auth:complete', { account });
|
|
2237
|
+
socketLoginSessions.delete(socket.id);
|
|
2238
|
+
// Story BS-8: accumulate the just-written credential into the multi-account store.
|
|
2239
|
+
// Login already made this account active, so the credentials file holds its credential
|
|
2240
|
+
// and accountInfoService supplied the email (or null → fallback key, AC1a). Fire-and-forget.
|
|
2241
|
+
accountStorageService.captureActiveCredential(account?.email ?? null).catch((err) => {
|
|
2242
|
+
log.warn(`BS-8: failed to capture credential after login: ${err instanceof Error ? err.message : String(err)}`);
|
|
2243
|
+
});
|
|
2244
|
+
},
|
|
2245
|
+
onError: (message) => {
|
|
2246
|
+
socket.emit('auth:error', { message });
|
|
2247
|
+
socketLoginSessions.delete(socket.id);
|
|
2248
|
+
},
|
|
2249
|
+
});
|
|
2250
|
+
socketLoginSessions.set(socket.id, session);
|
|
2251
|
+
session.start(cliBinaryPath);
|
|
2252
|
+
});
|
|
2253
|
+
socket.on('auth:select-method', (data) => {
|
|
2254
|
+
socketLoginSessions.get(socket.id)?.selectMethod(data.method);
|
|
2255
|
+
});
|
|
2256
|
+
socket.on('auth:submit-code', (data) => {
|
|
2257
|
+
socketLoginSessions.get(socket.id)?.submitCode(data.code);
|
|
2258
|
+
});
|
|
2259
|
+
socket.on('auth:logout', async () => {
|
|
2260
|
+
const ok = deleteCredentials();
|
|
2261
|
+
// Re-read usage credentials freshly (the deleted file → no token) so probing reflects logout.
|
|
2262
|
+
rateLimitProbeService.invalidateTokenCache();
|
|
2263
|
+
if (!ok) {
|
|
2264
|
+
socket.emit('auth:error', { message: 'Failed to delete credentials' });
|
|
2265
|
+
return;
|
|
2266
|
+
}
|
|
2267
|
+
// Refresh the in-memory account cache so a subsequent /account read reflects the logout.
|
|
2268
|
+
// The client transitions to the inline login flow optimistically (no success event needed).
|
|
2269
|
+
accountInfoService.refresh().catch(() => {
|
|
2270
|
+
/* best-effort — the file is gone regardless */
|
|
2271
|
+
});
|
|
2272
|
+
});
|
|
2149
2273
|
// Disconnect: detach socket from stream, DON'T abort or deny permissions
|
|
2150
|
-
socket.on('disconnect', () => {
|
|
2274
|
+
socket.on('disconnect', (reason) => {
|
|
2151
2275
|
const sessionId = socketToSession.get(socket.id);
|
|
2152
2276
|
if (sessionId) {
|
|
2153
2277
|
const stream = activeStreams.get(sessionId);
|
|
@@ -2216,8 +2340,15 @@ export async function initializeWebSocket(httpServer) {
|
|
|
2216
2340
|
if (terminalIds) {
|
|
2217
2341
|
socketTerminals.delete(socket.id);
|
|
2218
2342
|
}
|
|
2343
|
+
// Story BS-7: dispose any in-flight login PTY for this socket (the disposable login session
|
|
2344
|
+
// must not outlive its only client — it has no background-completion semantics like chat).
|
|
2345
|
+
const loginSession = socketLoginSessions.get(socket.id);
|
|
2346
|
+
if (loginSession) {
|
|
2347
|
+
loginSession.dispose();
|
|
2348
|
+
socketLoginSessions.delete(socket.id);
|
|
2349
|
+
}
|
|
2219
2350
|
connectedClients--;
|
|
2220
|
-
log.info(`Client disconnected. Total: ${connectedClients}`);
|
|
2351
|
+
log.info(`Client disconnected (reason=${reason}). Total: ${connectedClients}`);
|
|
2221
2352
|
// Stop polling when no clients connected
|
|
2222
2353
|
if (connectedClients === 0) {
|
|
2223
2354
|
rateLimitProbeService.stopPolling();
|
|
@@ -2515,7 +2646,10 @@ async function handleChatSend(stream, data, abortController, lang) {
|
|
|
2515
2646
|
// Story 33.3: resolve the effective engine mode (override > global > 'sdk' default).
|
|
2516
2647
|
// Captured once into a local so the progress-callback gating below reuses the same
|
|
2517
2648
|
// decision (no second resolve, and `engineMode === 'cli'` stays consistent).
|
|
2518
|
-
const engineMode = await
|
|
2649
|
+
const [engineMode, isBmadProject] = await Promise.all([
|
|
2650
|
+
projectService.getEffectiveEngineMode(workingDirectory),
|
|
2651
|
+
projectService.checkBmadProject(workingDirectory),
|
|
2652
|
+
]);
|
|
2519
2653
|
// Auto-compaction master switch (both engines). Default ON. Gates the engine-internal
|
|
2520
2654
|
// auto-compact (forwarded into each engine's settings) AND Hammoc's overflow-triggered
|
|
2521
2655
|
// /compact recovery below, so one toggle controls all auto-compaction.
|
|
@@ -2547,6 +2681,8 @@ async function handleChatSend(stream, data, abortController, lang) {
|
|
|
2547
2681
|
: { images }),
|
|
2548
2682
|
// Advanced settings from preferences
|
|
2549
2683
|
customSystemPrompt: effectivePrefs.customSystemPrompt,
|
|
2684
|
+
displayName: effectivePrefs.displayName,
|
|
2685
|
+
isBmadProject,
|
|
2550
2686
|
// maxThinkingTokens: legacy path; SDK docs say it takes precedence for backward-compat,
|
|
2551
2687
|
// which conflicts with adaptive mode on Opus 4.7+ (rejects enabled+budget). Skip on
|
|
2552
2688
|
// adaptive-capable models so the explicit `thinking` field governs.
|
|
@@ -2623,6 +2759,8 @@ async function handleChatSend(stream, data, abortController, lang) {
|
|
|
2623
2759
|
resolve,
|
|
2624
2760
|
interactionType: isAskUserQuestion ? 'question' : 'permission',
|
|
2625
2761
|
});
|
|
2762
|
+
if (isAskUserQuestion)
|
|
2763
|
+
emitQuestionChange(sessionIdRef.current || '', true);
|
|
2626
2764
|
});
|
|
2627
2765
|
if (isAskUserQuestion) {
|
|
2628
2766
|
const questions = input.questions;
|