mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-16 13:03:31 +08:00
Merge /goal desktop visibility fix
This commit is contained in:
commit
c75ff0bf2d
@ -1,5 +1,9 @@
|
||||
import { describe, expect, it } from 'bun:test'
|
||||
import { translateCliMessage } from '../ws/handler.js'
|
||||
import {
|
||||
createCurrentTurnLocalCommandForwarder,
|
||||
translateCliMessage,
|
||||
} from '../ws/handler.js'
|
||||
import { parseSlashCommand } from '../../utils/slashCommandParsing.js'
|
||||
|
||||
describe('WebSocket memory events', () => {
|
||||
it('forwards CLI memory_saved system messages to the desktop client', () => {
|
||||
@ -208,6 +212,37 @@ describe('WebSocket goal command events', () => {
|
||||
{ type: 'content_delta', text: 'Goal: active' },
|
||||
])
|
||||
})
|
||||
|
||||
it('allows the current slash command lifecycle through the pre-turn mute gate', () => {
|
||||
const shouldForward = createCurrentTurnLocalCommandForwarder(
|
||||
parseSlashCommand('/goal ship the smoke test'),
|
||||
)
|
||||
|
||||
expect(shouldForward({
|
||||
type: 'system',
|
||||
subtype: 'init',
|
||||
})).toBe(false)
|
||||
expect(shouldForward({
|
||||
type: 'system',
|
||||
subtype: 'local_command',
|
||||
content: '<command-name>/cost</command-name>\n<command-args></command-args>',
|
||||
})).toBe(false)
|
||||
expect(shouldForward({
|
||||
type: 'system',
|
||||
subtype: 'local_command',
|
||||
content: '<command-name>/goal</command-name>\n<command-args>ship the smoke test</command-args>',
|
||||
})).toBe(true)
|
||||
expect(shouldForward({
|
||||
type: 'system',
|
||||
subtype: 'local_command',
|
||||
content: '<local-command-stdout>Goal created.\nGoal: active\nObjective: ship the smoke test</local-command-stdout>',
|
||||
})).toBe(true)
|
||||
expect(shouldForward({
|
||||
type: 'system',
|
||||
subtype: 'local_command_output',
|
||||
content: 'late unrelated output',
|
||||
})).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('WebSocket stream event translation', () => {
|
||||
|
||||
@ -333,9 +333,16 @@ async function handleUserMessage(
|
||||
// Keep output muted until the current user turn is enqueued to avoid forwarding
|
||||
// any pre-turn SDK chatter as fresh chat history.
|
||||
let userMessageSent = false
|
||||
const shouldForwardCurrentTurnLocalCommand =
|
||||
createCurrentTurnLocalCommandForwarder(desktopSlashCommand)
|
||||
|
||||
rebindSessionOutput(sessionId, ws, {
|
||||
shouldForward: (cliMsg) => userMessageSent || (cliMsg.type === 'result' && cliMsg.is_error),
|
||||
shouldForward: (cliMsg) => {
|
||||
if (userMessageSent || (cliMsg.type === 'result' && cliMsg.is_error)) {
|
||||
return true
|
||||
}
|
||||
return shouldForwardCurrentTurnLocalCommand(cliMsg)
|
||||
},
|
||||
})
|
||||
|
||||
const sent = conversationService.sendMessage(
|
||||
@ -1324,6 +1331,56 @@ function getDesktopSlashCommand(content: string): ReturnType<typeof parseSlashCo
|
||||
return parsed
|
||||
}
|
||||
|
||||
export function createCurrentTurnLocalCommandForwarder(
|
||||
command: ReturnType<typeof parseSlashCommand>,
|
||||
): (cliMsg: any) => boolean {
|
||||
let awaitingCurrentTurnLocalCommandOutput = false
|
||||
|
||||
return (cliMsg: any) => {
|
||||
if (command && isMatchingCurrentTurnLocalCommand(cliMsg, command)) {
|
||||
awaitingCurrentTurnLocalCommandOutput = true
|
||||
return true
|
||||
}
|
||||
if (
|
||||
awaitingCurrentTurnLocalCommandOutput &&
|
||||
isLocalCommandOutputMessage(cliMsg)
|
||||
) {
|
||||
awaitingCurrentTurnLocalCommandOutput = false
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
function isMatchingCurrentTurnLocalCommand(
|
||||
cliMsg: any,
|
||||
command: NonNullable<ReturnType<typeof parseSlashCommand>>,
|
||||
): boolean {
|
||||
if (cliMsg?.type !== 'system' || cliMsg?.subtype !== 'local_command') {
|
||||
return false
|
||||
}
|
||||
const localCommand = extractLocalCommand(cliMsg.content ?? cliMsg.message)
|
||||
if (!localCommand) return false
|
||||
return (
|
||||
localCommand.name === command.commandName &&
|
||||
localCommand.args.trim() === command.args.trim()
|
||||
)
|
||||
}
|
||||
|
||||
function isLocalCommandOutputMessage(cliMsg: any): boolean {
|
||||
if (
|
||||
cliMsg?.type !== 'system' ||
|
||||
(cliMsg?.subtype !== 'local_command' &&
|
||||
cliMsg?.subtype !== 'local_command_output')
|
||||
) {
|
||||
return false
|
||||
}
|
||||
return extractLocalCommandOutput(
|
||||
cliMsg.content ?? cliMsg.message,
|
||||
{ allowUntagged: cliMsg.subtype === 'local_command_output' },
|
||||
) !== null
|
||||
}
|
||||
|
||||
function extractLocalCommandOutput(
|
||||
content: unknown,
|
||||
options: { allowUntagged?: boolean } = {},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user