hammoc 1.7.0 → 1.7.2

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.
Files changed (82) hide show
  1. package/README.md +6 -2
  2. package/package.json +1 -1
  3. package/packages/client/dist/assets/{agentExampleHighlight-7Olvqdpf.js → agentExampleHighlight-De1SlBXH.js} +1 -1
  4. package/packages/client/dist/assets/{commandTokenHighlight-DtKwh4lx.js → commandTokenHighlight-COQi5YnH.js} +1 -1
  5. package/packages/client/dist/assets/index-BsHMOF5r.css +32 -0
  6. package/packages/client/dist/assets/{index-Bee52CKG.js → index-CQgqPGOG.js} +483 -469
  7. package/packages/client/dist/assets/{index-DLHBUw8c.js → index-D8XvfvVS.js} +1 -1
  8. package/packages/client/dist/assets/{snippetTokenHighlight-C8O688f4.js → snippetTokenHighlight-jMAHlrFd.js} +1 -1
  9. package/packages/client/dist/index.html +2 -2
  10. package/packages/client/dist/sw.js +1 -1
  11. package/packages/server/dist/controllers/gitController.d.ts.map +1 -1
  12. package/packages/server/dist/controllers/gitController.js +37 -0
  13. package/packages/server/dist/controllers/gitController.js.map +1 -1
  14. package/packages/server/dist/controllers/projectController.d.ts.map +1 -1
  15. package/packages/server/dist/controllers/projectController.js +3 -1
  16. package/packages/server/dist/controllers/projectController.js.map +1 -1
  17. package/packages/server/dist/controllers/sessionController.d.ts.map +1 -1
  18. package/packages/server/dist/controllers/sessionController.js +3 -1
  19. package/packages/server/dist/controllers/sessionController.js.map +1 -1
  20. package/packages/server/dist/handlers/streamCallbacks.d.ts +2 -0
  21. package/packages/server/dist/handlers/streamCallbacks.d.ts.map +1 -1
  22. package/packages/server/dist/handlers/streamCallbacks.js +4 -4
  23. package/packages/server/dist/handlers/streamCallbacks.js.map +1 -1
  24. package/packages/server/dist/handlers/websocket.d.ts +6 -0
  25. package/packages/server/dist/handlers/websocket.d.ts.map +1 -1
  26. package/packages/server/dist/handlers/websocket.js +68 -5
  27. package/packages/server/dist/handlers/websocket.js.map +1 -1
  28. package/packages/server/dist/locales/en/server.json +2 -0
  29. package/packages/server/dist/locales/es/server.json +2 -0
  30. package/packages/server/dist/locales/ja/server.json +2 -0
  31. package/packages/server/dist/locales/ko/server.json +2 -0
  32. package/packages/server/dist/locales/pt/server.json +2 -0
  33. package/packages/server/dist/locales/zh-CN/server.json +2 -0
  34. package/packages/server/dist/services/chatService.js +1 -1
  35. package/packages/server/dist/services/chatService.js.map +1 -1
  36. package/packages/server/dist/services/cliChatEngine.js +2 -2
  37. package/packages/server/dist/services/cliChatEngine.js.map +1 -1
  38. package/packages/server/dist/services/dashboardService.d.ts.map +1 -1
  39. package/packages/server/dist/services/dashboardService.js +6 -1
  40. package/packages/server/dist/services/dashboardService.js.map +1 -1
  41. package/packages/server/dist/services/gitService.d.ts +2 -0
  42. package/packages/server/dist/services/gitService.d.ts.map +1 -1
  43. package/packages/server/dist/services/gitService.js +41 -3
  44. package/packages/server/dist/services/gitService.js.map +1 -1
  45. package/packages/server/dist/services/queueService.d.ts +1 -0
  46. package/packages/server/dist/services/queueService.d.ts.map +1 -1
  47. package/packages/server/dist/services/queueService.js +15 -3
  48. package/packages/server/dist/services/queueService.js.map +1 -1
  49. package/packages/server/dist/services/workspaceContext.d.ts +2 -1
  50. package/packages/server/dist/services/workspaceContext.d.ts.map +1 -1
  51. package/packages/server/dist/services/workspaceContext.js +10 -2
  52. package/packages/server/dist/services/workspaceContext.js.map +1 -1
  53. package/packages/server/dist/utils/cliDebugLog.d.ts +4 -2
  54. package/packages/server/dist/utils/cliDebugLog.d.ts.map +1 -1
  55. package/packages/server/dist/utils/cliDebugLog.js +8 -2
  56. package/packages/server/dist/utils/cliDebugLog.js.map +1 -1
  57. package/packages/server/resources/bmad-method/4.44.3/LICENSE +30 -0
  58. package/packages/server/resources/manual/02-chat.md +2 -2
  59. package/packages/server/resources/manual/03-sessions.md +1 -0
  60. package/packages/server/resources/manual/05-projects.md +2 -2
  61. package/packages/server/resources/manual/07-git.md +23 -2
  62. package/packages/server/resources/manual/08-terminal.md +24 -1
  63. package/packages/server/resources/manual/11-bmad-method-integration.md +1 -0
  64. package/packages/server/resources/manual/13-settings.md +25 -25
  65. package/packages/shared/dist/types/dashboard.d.ts +1 -0
  66. package/packages/shared/dist/types/dashboard.d.ts.map +1 -1
  67. package/packages/shared/dist/types/git.d.ts +12 -0
  68. package/packages/shared/dist/types/git.d.ts.map +1 -1
  69. package/packages/shared/dist/types/git.js +10 -0
  70. package/packages/shared/dist/types/git.js.map +1 -1
  71. package/packages/shared/dist/types/preferences.d.ts +1 -0
  72. package/packages/shared/dist/types/preferences.d.ts.map +1 -1
  73. package/packages/shared/dist/types/preferences.js.map +1 -1
  74. package/packages/shared/dist/types/sdk.d.ts +2 -0
  75. package/packages/shared/dist/types/sdk.d.ts.map +1 -1
  76. package/packages/shared/dist/types/sdk.js.map +1 -1
  77. package/packages/shared/dist/types/session.d.ts +1 -0
  78. package/packages/shared/dist/types/session.d.ts.map +1 -1
  79. package/packages/shared/dist/types/session.js.map +1 -1
  80. package/packages/shared/dist/types/websocket.d.ts +6 -0
  81. package/packages/shared/dist/types/websocket.d.ts.map +1 -1
  82. package/packages/client/dist/assets/index-CVy582lU.css +0 -32
@@ -456,6 +456,38 @@ export function isSessionStreaming(sessionId) {
456
456
  const stream = activeStreams.get(sessionId);
457
457
  return !!stream && stream.status === 'running';
458
458
  }
459
+ /** Check if a session has any pending AskUserQuestion interactions */
460
+ export function sessionHasPendingQuestion(sessionId) {
461
+ const stream = activeStreams.get(sessionId);
462
+ if (!stream)
463
+ return false;
464
+ for (const p of stream.pendingPermissions.values()) {
465
+ if (p.interactionType === 'question')
466
+ return true;
467
+ }
468
+ return false;
469
+ }
470
+ /** Get pending AskUserQuestion counts grouped by project slug (in-memory, no I/O) */
471
+ export function getPendingQuestionCountsByProject() {
472
+ const counts = new Map();
473
+ for (const [sessionId, stream] of activeStreams.entries()) {
474
+ if (stream.status !== 'running')
475
+ continue;
476
+ let hasQuestion = false;
477
+ for (const p of stream.pendingPermissions.values()) {
478
+ if (p.interactionType === 'question') {
479
+ hasQuestion = true;
480
+ break;
481
+ }
482
+ }
483
+ if (hasQuestion) {
484
+ const slug = sessionProjectMap.get(sessionId);
485
+ if (slug)
486
+ counts.set(slug, (counts.get(slug) ?? 0) + 1);
487
+ }
488
+ }
489
+ return counts;
490
+ }
459
491
  /** Get session IDs that have active socket connections for a given project */
460
492
  export function getJoinedSessionIdsByProject(projectSlug) {
461
493
  const sessionIds = new Set();
@@ -566,6 +598,15 @@ function cleanupStream(streamKey, expectedStream) {
566
598
  // Only delete from activeStreams and clean up socket mappings if the stream
567
599
  // hasn't been replaced. When replaced, the new stream owns those resources.
568
600
  if (!replaced) {
601
+ // Clear pending question state before removing the stream
602
+ if (current) {
603
+ for (const p of current.pendingPermissions.values()) {
604
+ if (p.interactionType === 'question') {
605
+ emitQuestionChange(streamKey, false);
606
+ break;
607
+ }
608
+ }
609
+ }
569
610
  activeStreams.delete(streamKey);
570
611
  for (const [sockId, sessId] of socketToSession.entries()) {
571
612
  if (sessId === streamKey)
@@ -719,6 +760,17 @@ function emitStreamChange(sessionId, active, projectSlug) {
719
760
  }
720
761
  }
721
762
  }
763
+ /**
764
+ * Emit session:question-change when an AskUserQuestion becomes pending or is resolved.
765
+ * Scoped to the project room so only relevant session list viewers receive it.
766
+ */
767
+ function emitQuestionChange(sessionId, hasPendingQuestion) {
768
+ const projectSlug = sessionProjectMap.get(sessionId);
769
+ if (projectSlug) {
770
+ io.to(`project:${projectSlug}`).emit('session:question-change', { sessionId, hasPendingQuestion, projectSlug });
771
+ triggerDashboardStatusChange(projectSlug);
772
+ }
773
+ }
722
774
  /**
723
775
  * Broadcast session:stream-change to project room (or all clients as fallback).
724
776
  * Used by queue service to signal stream start/end.
@@ -1032,9 +1084,15 @@ export async function initializeWebSocket(httpServer) {
1032
1084
  if (!sessionId)
1033
1085
  return;
1034
1086
  const stream = activeStreams.get(sessionId);
1035
- if (stream?.pendingPermissions.has(data.requestId)) {
1036
- stream.pendingPermissions.get(data.requestId).resolve({ approved: data.approved, response: data.response });
1087
+ if (!stream)
1088
+ return;
1089
+ const pending = stream.pendingPermissions.get(data.requestId);
1090
+ if (pending) {
1091
+ const wasQuestion = pending.interactionType === 'question';
1092
+ pending.resolve({ approved: data.approved, response: data.response });
1037
1093
  stream.pendingPermissions.delete(data.requestId);
1094
+ if (wasQuestion)
1095
+ emitQuestionChange(sessionId, sessionHasPendingQuestion(sessionId));
1038
1096
  // Broadcast the actual resolution to all OTHER viewers so their
1039
1097
  // tool/interactive cards can show the correct approve/deny state.
1040
1098
  // Also buffer via createStreamEmit so reconnecting clients see the
@@ -1281,7 +1339,7 @@ export async function initializeWebSocket(httpServer) {
1281
1339
  socket.emit('stream:history', { sessionId, messages: buf.messages });
1282
1340
  }
1283
1341
  socket.emit('stream:status', { active: true, sessionId, permissionMode: freshMode });
1284
- socket.emit('stream:buffer-replay', { sessionId, events: [...freshStream.buffer] });
1342
+ socket.emit('stream:buffer-replay', { sessionId, events: [...freshStream.buffer], engineMode: freshStream.engineMode });
1285
1343
  freshStream.sockets.add(socket);
1286
1344
  return;
1287
1345
  }
@@ -1297,7 +1355,7 @@ export async function initializeWebSocket(httpServer) {
1297
1355
  socket.emit('stream:history', { sessionId, messages: buf.messages });
1298
1356
  }
1299
1357
  socket.emit('stream:status', { active: true, sessionId, permissionMode });
1300
- socket.emit('stream:buffer-replay', { sessionId, events: [...completedStream.buffer] });
1358
+ socket.emit('stream:buffer-replay', { sessionId, events: [...completedStream.buffer], engineMode: completedStream.engineMode });
1301
1359
  completedStream.sockets.add(socket);
1302
1360
  return;
1303
1361
  }
@@ -1368,7 +1426,7 @@ export async function initializeWebSocket(httpServer) {
1368
1426
  }
1369
1427
  socket.emit('stream:status', { active: true, sessionId, permissionMode });
1370
1428
  // Replay raw event buffer so the client can build streaming segments
1371
- socket.emit('stream:buffer-replay', { sessionId, events: [...stream.buffer] });
1429
+ socket.emit('stream:buffer-replay', { sessionId, events: [...stream.buffer], engineMode: stream.engineMode });
1372
1430
  // NOW add to broadcast set — live events flow from here
1373
1431
  stream.sockets.add(socket);
1374
1432
  });
@@ -2522,6 +2580,7 @@ async function handleChatSend(stream, data, abortController, lang) {
2522
2580
  const autoCompactEnabled = effectivePrefs.autoCompactEnabled ?? true;
2523
2581
  const chatService = createChatEngine(engineMode, { workingDirectory, permissionMode, cliBinaryPath: effectivePrefs.cliBinaryPath, cliShowThinkingSummaries: effectivePrefs.cliShowThinkingSummaries, cliResumeChoice: effectivePrefs.cliResumeChoice, autoCompactEnabled, planModeBypassBehavior: effectivePrefs.planModeBypassBehavior });
2524
2582
  stream.chatService = chatService;
2583
+ stream.engineMode = engineMode;
2525
2584
  const effectiveEffort = clampEffortForModel(effort ?? effectivePrefs.defaultEffort, model);
2526
2585
  // Opus 4.7+ flipped `thinking.display` default to 'omitted' — ThinkingBlock UI stays blank
2527
2586
  // unless we explicitly opt in. For adaptive-thinking models, forward an explicit `thinking`
@@ -2546,6 +2605,7 @@ async function handleChatSend(stream, data, abortController, lang) {
2546
2605
  : { images }),
2547
2606
  // Advanced settings from preferences
2548
2607
  customSystemPrompt: effectivePrefs.customSystemPrompt,
2608
+ displayName: effectivePrefs.displayName,
2549
2609
  // maxThinkingTokens: legacy path; SDK docs say it takes precedence for backward-compat,
2550
2610
  // which conflicts with adaptive mode on Opus 4.7+ (rejects enabled+budget). Skip on
2551
2611
  // adaptive-capable models so the explicit `thinking` field governs.
@@ -2622,6 +2682,8 @@ async function handleChatSend(stream, data, abortController, lang) {
2622
2682
  resolve,
2623
2683
  interactionType: isAskUserQuestion ? 'question' : 'permission',
2624
2684
  });
2685
+ if (isAskUserQuestion)
2686
+ emitQuestionChange(sessionIdRef.current || '', true);
2625
2687
  });
2626
2688
  if (isAskUserQuestion) {
2627
2689
  const questions = input.questions;
@@ -2773,6 +2835,7 @@ async function handleChatSend(stream, data, abortController, lang) {
2773
2835
  // slug resolution cannot disrupt the stream.
2774
2836
  mcpRecorder: createMcpCallRecorder(() => projectService.findProjectByPath(workingDirectory).then((p) => p?.projectSlug)),
2775
2837
  backgroundTracker,
2838
+ engineMode,
2776
2839
  }, {
2777
2840
  onCallbackActivity: (source) => resetTimeout(source),
2778
2841
  onSessionIdResolved: (sid) => {