@jacexh/claude-web-console 0.11.2 → 0.11.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jacexh/claude-web-console",
3
- "version": "0.11.2",
3
+ "version": "0.11.3",
4
4
  "description": "Web-based console for Claude Code — manage sessions, switch models, preview artifacts",
5
5
  "type": "module",
6
6
  "bin": {
@@ -11,7 +11,7 @@ import { describe, it, expect } from 'vitest'
11
11
  * We extract the logic into a pure function so it can be tested
12
12
  * without mocking the full SessionManager.
13
13
  */
14
- import { shouldBroadcastTurnStarted, shouldResetToIdleOnStreamEnd } from '../turn-lifecycle'
14
+ import { shouldBroadcastTurnStarted, shouldResetToIdleOnStreamEnd, isTurnMessage } from '../turn-lifecycle'
15
15
 
16
16
  describe('shouldBroadcastTurnStarted', () => {
17
17
  it('returns true for the first message of a turn', () => {
@@ -65,3 +65,37 @@ describe('shouldResetToIdleOnStreamEnd', () => {
65
65
  expect(shouldResetToIdleOnStreamEnd('stopped')).toBe(false)
66
66
  })
67
67
  })
68
+
69
+ describe('isTurnMessage', () => {
70
+ it('returns false for system/init (session initialization, not a turn)', () => {
71
+ expect(isTurnMessage({ type: 'system', subtype: 'init' })).toBe(false)
72
+ })
73
+
74
+ it('returns true for assistant messages (agent generating)', () => {
75
+ expect(isTurnMessage({ type: 'assistant' })).toBe(true)
76
+ })
77
+
78
+ it('returns true for user messages (tool results)', () => {
79
+ expect(isTurnMessage({ type: 'user' })).toBe(true)
80
+ })
81
+
82
+ it('returns true for result messages (turn complete)', () => {
83
+ expect(isTurnMessage({ type: 'result' })).toBe(true)
84
+ })
85
+
86
+ it('returns true for system/task_started', () => {
87
+ expect(isTurnMessage({ type: 'system', subtype: 'task_started' })).toBe(true)
88
+ })
89
+
90
+ it('returns true for system/task_progress', () => {
91
+ expect(isTurnMessage({ type: 'system', subtype: 'task_progress' })).toBe(true)
92
+ })
93
+
94
+ it('returns true for system/task_notification', () => {
95
+ expect(isTurnMessage({ type: 'system', subtype: 'task_notification' })).toBe(true)
96
+ })
97
+
98
+ it('returns false for system/init even with extra fields', () => {
99
+ expect(isTurnMessage({ type: 'system', subtype: 'init', model: 'claude-sonnet' })).toBe(false)
100
+ })
101
+ })
@@ -17,7 +17,7 @@ import { join } from 'node:path'
17
17
  import { homedir } from 'node:os'
18
18
  import type { FastifyBaseLogger } from 'fastify'
19
19
  import type { SessionInfo, EffortLevel } from './types.js'
20
- import { shouldBroadcastTurnStarted, shouldResetToIdleOnStreamEnd, type TurnState } from './turn-lifecycle.js'
20
+ import { shouldBroadcastTurnStarted, shouldResetToIdleOnStreamEnd, isTurnMessage, type TurnState } from './turn-lifecycle.js'
21
21
  import { SessionStatusTracker } from './session-status.js'
22
22
 
23
23
  type PermissionResolver = {
@@ -537,8 +537,8 @@ export class SessionManager {
537
537
  } as unknown as SDKMessage))
538
538
  }
539
539
 
540
- // Set session status to running on first message of each turn
541
- if (shouldBroadcastTurnStarted(turnState)) {
540
+ // Set session status to running on first turn message (skip system/init)
541
+ if (isTurnMessage(msgAny) && shouldBroadcastTurnStarted(turnState)) {
542
542
  this.sessionStatus.set(sessionId, 'running')
543
543
  }
544
544
  this.broadcast(sessionId, (l) => l.onMessage(sessionId, msg))
@@ -13,3 +13,9 @@ export function shouldBroadcastTurnStarted(state: TurnState): boolean {
13
13
  export function shouldResetToIdleOnStreamEnd(currentStatus: string): boolean {
14
14
  return currentStatus === 'running'
15
15
  }
16
+
17
+ /** Returns true if this SDK message is part of an active turn (not session init). */
18
+ export function isTurnMessage(msg: Record<string, unknown>): boolean {
19
+ if (msg.type === 'system' && msg.subtype === 'init') return false
20
+ return true
21
+ }